@nsshunt/stsfhirpg 1.2.20 → 1.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","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","#poolManager","#poolManager","#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","../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/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","import { x64 } from 'murmurhash3js';\n\n//\n// TYPES\n//\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\n/**\n * Converts first 64 bits of MurmurHash3_x64_128 result into signed BigInt\n */\nexport function murmur64Signed(input: string): bigint {\n const hex128 = x64.hash128(input);\n const buf = Buffer.from(hex128.slice(0, 16), 'hex');\n return buf.readBigInt64LE(0);\n}\n\n/**\n * Compute hash for a normalized string search parameter\n */\nexport function hashStringParam(input: string, normalize: boolean): bigint {\n if (normalize === true) {\n const normalized = normalizeStringParam(input);\n return murmur64Signed(normalized);\n } else {\n return murmur64Signed(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 murmur64Signed(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 murmur64Signed(reference);\n}\n\n/**\n * Compute hash for a URI parameter (optionally lowercased)\n */\nexport function hashUriParam(uri: string, lowercase = false): bigint {\n return murmur64Signed(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 { PoolClient } from 'pg';\nimport { IResource } from '../../fhir-utils/commonTypes.js'\nimport { PGPoolManager } from './pgpoolmanager.js'\nimport { defaultLogger } from '@nsshunt/stsutils';\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 {\n #poolManager: PGPoolManager;\n\n constructor(poolManager: PGPoolManager) {\n this.#poolManager = poolManager;\n }\n\n async InsertResourceEx(client: PoolClient, data: NamedResourceInsert): Promise<void> {\n try {\n 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 `,\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 } catch (error) {\n defaultLogger.error(`DBSTSResource:InsertResource(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async InsertResource(data: NamedResourceInsert): Promise<void> {\n try {\n const client = await this.#poolManager.connectReadWrite();\n try {\n await this.InsertResourceEx(client, data);\n } catch (error) {\n defaultLogger.error(`DBSTSResource:InsertResource(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:InsertResource(): Connection Error: [${error}]`)\n }\n }\n\n async UpdateResourceRecordEx(client: PoolClient, data: NamedResourceUpdate): Promise<boolean | 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 `,\n [BigInt(data.RES_UPDATED), data.RES_ID, data.RES_TYPE, data.RES_VER]\n );\n return (res.rowCount ? res.rowCount > 0 : false);\n } catch (error) {\n defaultLogger.error(`DBSTSResource:UpdateResourceRecordEx(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async UpdateResourceRecord(data: NamedResourceUpdate): Promise<boolean | undefined> {\n try {\n const client = await this.#poolManager.connectReadWrite();\n try {\n return await this.UpdateResourceRecordEx(client, data);\n } catch (error) {\n defaultLogger.error(`DBSTSResource:UpdateResourceRecord-1(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:UpdateResourceRecord-2(): Connection Error: [${error}]`)\n }\n }\n\n async DeleteResourceRecordEx(client: PoolClient, data: NamedResourceDelete): Promise<boolean | 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 `,\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.rowCount ? res.rowCount > 0 : false);\n } catch (error) {\n defaultLogger.error(`DBSTSResource:DeleteResourceRecord(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async DeleteResourceRecord(data: NamedResourceDelete): Promise<boolean | undefined> {\n try {\n const client = await this.#poolManager.connectReadWrite();\n try {\n return await this.DeleteResourceRecordEx(client, data);\n } catch (error) {\n defaultLogger.error(`DBSTSResource:DeleteResourceRecord(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:DeleteResourceRecord(): Connection Error: [${error}]`)\n }\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 defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n throw (error);\n }\n }\n\n async ReadResourceRecord(PID: string): Promise<IResource | undefined> {\n try {\n const client = await this.#poolManager.connectReadOnly();\n try {\n return await this.ReadResourceRecordEx(client, PID);\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Connection Error: [${error}]`)\n }\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 defaultLogger.error(`DBSTSResource:ReadAllResourceRecords(): Query Error: [${error}]`)\n throw error;\n }\n }\n \n async ReadAllResourceRecords(): Promise<IResource[] | undefined> {\n try {\n const client = await this.#poolManager.connectReadOnly();\n try {\n return await this.ReadAllResourceRecordsEx(client);\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadAllResourceRecords(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadAllResourceRecords(): Connection Error: [${error}]`)\n }\n }\n}\n","import { PGPoolManager } from './pgpoolmanager.js'\nimport { IResourceVersion } from '../../fhir-utils/commonTypes.js'\nimport { defaultLogger } from '@nsshunt/stsutils';\nimport { PoolClient } from 'pg';\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 {\n #poolManager: PGPoolManager;\n\n constructor(poolManager: PGPoolManager) {\n this.#poolManager = poolManager;\n }\n\n async InsertResourceVersionEx(client: PoolClient, data: NamedResourceVersionInsert): Promise<void> {\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\n 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 `,values);\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): Query Error: [${error}]`)\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values PID: [${values[0]}]`)\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values PARTITION_ID: [${values[1]}]`)\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values PARTITION_DATE: [${values[2]}]`)\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values RES_ID: [${values[3]}]`)\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values RES_TYPE: [${values[4]}]`)\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values RES_VER: [${values[5]}]`)\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values OPERATION: [${values[6]}]`)\n throw error;\n }\n }\n\n async InsertResourceVersion(data: NamedResourceVersionInsert): Promise<void> {\n try {\n const client = await this.#poolManager.connectReadWrite();\n try {\n await this.InsertResourceVersionEx(client, data);\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): Connection Error: [${error}]`)\n }\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 defaultLogger.error(`DBSTSResourceVersion:ReadResourceVersionRecord(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async ReadResourceVersionRecord(PID: string, RES_VER: number): Promise<IResourceVersion | undefined> {\n try {\n const client = await this.#poolManager.connectReadWrite();\n try {\n return await this.ReadResourceVersionRecordEx(client, PID, RES_VER);\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:ReadResourceVersionRecord(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:ReadResourceVersionRecord(): Connection Error: [${error}]`)\n }\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 defaultLogger.error(`DBSTSResourceVersion:ReadAllResourceVersionRecords(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async ReadAllResourceVersionRecords(): Promise<IResourceVersion[] | undefined> {\n try {\n const client = await this.#poolManager.connectReadWrite();\n try {\n return await this.ReadAllResourceVersionRecordsEx(client);\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:ReadAllResourceVersionRecords(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:ReadAllResourceVersionRecords(): Connection Error: [${error}]`)\n }\n }\n\n /*\n async UpdateResourceVersionRecord(data: NamedResourceVersionUpdate): Promise<boolean | undefined> {\n try {\n const client = await this.#poolManager.connectReadWrite();\n try {\n const res = await client.query(\n `\n UPDATE stsresfhirver\n SET RES_VER = RES_VER + 1,\n RES = $1\n WHERE RES_ID = $2 AND RES_VER = $3\n `,\n [data.RES, data.RES_ID, data.RES_VER]\n );\n return (res.rowCount ? res.rowCount > 0 : false);\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:UpdateResourceVersionRecord(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:UpdateResourceVersionRecord(): Connection Error: [${error}]`)\n }\n }\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 } 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(this.#poolManager);\n this.#dbSTSResourceVersion = new DBSTSResourceVersion(this.#poolManager);\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 /*\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 try {\n let PK = randomUUID();\n const RES_ID = resource.id!;\n const RES_TYPE = resource.resourceType;\n const RES = JSON.stringify(resource);\n const now = new Date().getTime();\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.connectReadWrite();\n useTransaction = true;\n }\n try {\n if (useTransaction) {\n await client.query('BEGIN');\n }\n\n const resourceRunResult = await this.#dbSTSResource.InsertResourceEx(client, {\n PID: PK,\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\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: 1,\n OPERATION: 'POST',\n RES\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 } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`PGFhirAccessLayer:CreateResource(): [${error}]`);\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 try {\n const RES_ID = resource.id!;\n const RES_TYPE = resource.resourceType;\n const RES = JSON.stringify(resource);\n const now = new Date().getTime();\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.connectReadWrite();\n useTransaction = true;\n }\n try {\n if (useTransaction) {\n await client.query('BEGIN');\n }\n\n const resourceRunResult = await this.#dbSTSResource.UpdateResourceRecordEx(client, {\n RES_TYPE,\n RES_ID,\n RES_VER,\n RES_UPDATED: now\n });\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: (RES_VER + 1),\n OPERATION: operation,\n RES\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 } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`PGFhirAccessLayer:UpdateResource(): [${error}]`);\n }\n }\n }\n\n DeleteResource = async (resource: Resource, RES_VER: number, transactionHandle?: string): Promise<Resource | undefined> => {\n if (this.#poolManager) {\n try {\n const RES_ID = resource.id!;\n const RES_TYPE = resource.resourceType;\n\n const now = new Date(DateTime.fromISO(resource.meta!.lastUpdated as string).toJSDate()).getTime();\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.connectReadWrite();\n useTransaction = true;\n }\n try {\n if (useTransaction) {\n await client.query('BEGIN');\n }\n\n const resourceRunResult = 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\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: (RES_VER + 1),\n OPERATION: 'DELETE',\n RES: ''\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 } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`PGFhirAccessLayer:DeleteResource(): [${error}]`);\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 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\n ReadResourceRecordWithVersion = async (RES_TYPE: string, RES_ID: string, RES_VER: number, transactionHandle?: string): Promise<IResource | undefined> => {\n if (this.#poolManager) {\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\n ReadResourceInstanceWithAllVersions = async (RES_TYPE: string, RES_ID: string, transactionHandle?: string): Promise<IResource[] | undefined> => {\n if (this.#poolManager) {\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\n ReadResourcesWithAllVersions = async (RES_TYPE: string, transactionHandle?: string): Promise<IResource[] | undefined> => {\n if (this.#poolManager) {\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\n ReadAllResourcesWithVersions = async (transactionHandle?: string) => {\n if (this.#poolManager) {\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\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 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\n ExecuteReadQuery = async (queryData: any, transactionHandle?: string): Promise<any> => {\n if (this.#poolManager) {\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\n TruncateAll = async () => {\n if (this.#poolManager) {\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}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","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","#poolManager","#poolManager","#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/cuint/lib/uint32.js","../node_modules/cuint/lib/uint64.js","../node_modules/cuint/index.js","../node_modules/xxhashjs/lib/xxhash.js","../node_modules/xxhashjs/lib/xxhash64.js","../node_modules/xxhashjs/lib/index.js","../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/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","/**\n\tC-like unsigned 32 bits integers in Javascript\n\tCopyright (C) 2013, Pierre Curto\n\tMIT license\n */\n;(function (root) {\n\n\t// Local cache for typical radices\n\tvar radixPowerCache = {\n\t\t36: UINT32( Math.pow(36, 5) )\n\t,\t16: UINT32( Math.pow(16, 7) )\n\t,\t10: UINT32( Math.pow(10, 9) )\n\t,\t2: UINT32( Math.pow(2, 30) )\n\t}\n\tvar radixCache = {\n\t\t36: UINT32(36)\n\t,\t16: UINT32(16)\n\t,\t10: UINT32(10)\n\t,\t2: UINT32(2)\n\t}\n\n\t/**\n\t *\tRepresents an unsigned 32 bits integer\n\t * @constructor\n\t * @param {Number|String|Number} low bits | integer as a string \t\t | integer as a number\n\t * @param {Number|Number|Undefined} high bits | radix (optional, default=10)\n\t * @return \n\t */\n\tfunction UINT32 (l, h) {\n\t\tif ( !(this instanceof UINT32) )\n\t\t\treturn new UINT32(l, h)\n\n\t\tthis._low = 0\n\t\tthis._high = 0\n\t\tthis.remainder = null\n\t\tif (typeof h == 'undefined')\n\t\t\treturn fromNumber.call(this, l)\n\n\t\tif (typeof l == 'string')\n\t\t\treturn fromString.call(this, l, h)\n\n\t\tfromBits.call(this, l, h)\n\t}\n\n\t/**\n\t * Set the current _UINT32_ object with its low and high bits\n\t * @method fromBits\n\t * @param {Number} low bits\n\t * @param {Number} high bits\n\t * @return ThisExpression\n\t */\n\tfunction fromBits (l, h) {\n\t\tthis._low = l | 0\n\t\tthis._high = h | 0\n\n\t\treturn this\n\t}\n\tUINT32.prototype.fromBits = fromBits\n\n\t/**\n\t * Set the current _UINT32_ object from a number\n\t * @method fromNumber\n\t * @param {Number} number\n\t * @return ThisExpression\n\t */\n\tfunction fromNumber (value) {\n\t\tthis._low = value & 0xFFFF\n\t\tthis._high = value >>> 16\n\n\t\treturn this\n\t}\n\tUINT32.prototype.fromNumber = fromNumber\n\n\t/**\n\t * Set the current _UINT32_ object from a string\n\t * @method fromString\n\t * @param {String} integer as a string\n\t * @param {Number} radix (optional, default=10)\n\t * @return ThisExpression\n\t */\n\tfunction fromString (s, radix) {\n\t\tvar value = parseInt(s, radix || 10)\n\n\t\tthis._low = value & 0xFFFF\n\t\tthis._high = value >>> 16\n\n\t\treturn this\n\t}\n\tUINT32.prototype.fromString = fromString\n\n\t/**\n\t * Convert this _UINT32_ to a number\n\t * @method toNumber\n\t * @return {Number} the converted UINT32\n\t */\n\tUINT32.prototype.toNumber = function () {\n\t\treturn (this._high * 65536) + this._low\n\t}\n\n\t/**\n\t * Convert this _UINT32_ to a string\n\t * @method toString\n\t * @param {Number} radix (optional, default=10)\n\t * @return {String} the converted UINT32\n\t */\n\tUINT32.prototype.toString = function (radix) {\n\t\treturn this.toNumber().toString(radix || 10)\n\t}\n\n\t/**\n\t * Add two _UINT32_. The current _UINT32_ stores the result\n\t * @method add\n\t * @param {Object} other UINT32\n\t * @return ThisExpression\n\t */\n\tUINT32.prototype.add = function (other) {\n\t\tvar a00 = this._low + other._low\n\t\tvar a16 = a00 >>> 16\n\n\t\ta16 += this._high + other._high\n\n\t\tthis._low = a00 & 0xFFFF\n\t\tthis._high = a16 & 0xFFFF\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Subtract two _UINT32_. The current _UINT32_ stores the result\n\t * @method subtract\n\t * @param {Object} other UINT32\n\t * @return ThisExpression\n\t */\n\tUINT32.prototype.subtract = function (other) {\n\t\t//TODO inline\n\t\treturn this.add( other.clone().negate() )\n\t}\n\n\t/**\n\t * Multiply two _UINT32_. The current _UINT32_ stores the result\n\t * @method multiply\n\t * @param {Object} other UINT32\n\t * @return ThisExpression\n\t */\n\tUINT32.prototype.multiply = function (other) {\n\t\t/*\n\t\t\ta = a00 + a16\n\t\t\tb = b00 + b16\n\t\t\ta*b = (a00 + a16)(b00 + b16)\n\t\t\t\t= a00b00 + a00b16 + a16b00 + a16b16\n\n\t\t\ta16b16 overflows the 32bits\n\t\t */\n\t\tvar a16 = this._high\n\t\tvar a00 = this._low\n\t\tvar b16 = other._high\n\t\tvar b00 = other._low\n\n/* Removed to increase speed under normal circumstances (i.e. not multiplying by 0 or 1)\n\t\t// this == 0 or other == 1: nothing to do\n\t\tif ((a00 == 0 && a16 == 0) || (b00 == 1 && b16 == 0)) return this\n\n\t\t// other == 0 or this == 1: this = other\n\t\tif ((b00 == 0 && b16 == 0) || (a00 == 1 && a16 == 0)) {\n\t\t\tthis._low = other._low\n\t\t\tthis._high = other._high\n\t\t\treturn this\n\t\t}\n*/\n\n\t\tvar c16, c00\n\t\tc00 = a00 * b00\n\t\tc16 = c00 >>> 16\n\n\t\tc16 += a16 * b00\n\t\tc16 &= 0xFFFF\t\t// Not required but improves performance\n\t\tc16 += a00 * b16\n\n\t\tthis._low = c00 & 0xFFFF\n\t\tthis._high = c16 & 0xFFFF\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Divide two _UINT32_. The current _UINT32_ stores the result.\n\t * The remainder is made available as the _remainder_ property on\n\t * the _UINT32_ object. It can be null, meaning there are no remainder.\n\t * @method div\n\t * @param {Object} other UINT32\n\t * @return ThisExpression\n\t */\n\tUINT32.prototype.div = function (other) {\n\t\tif ( (other._low == 0) && (other._high == 0) ) throw Error('division by zero')\n\n\t\t// other == 1\n\t\tif (other._high == 0 && other._low == 1) {\n\t\t\tthis.remainder = new UINT32(0)\n\t\t\treturn this\n\t\t}\n\n\t\t// other > this: 0\n\t\tif ( other.gt(this) ) {\n\t\t\tthis.remainder = this.clone()\n\t\t\tthis._low = 0\n\t\t\tthis._high = 0\n\t\t\treturn this\n\t\t}\n\t\t// other == this: 1\n\t\tif ( this.eq(other) ) {\n\t\t\tthis.remainder = new UINT32(0)\n\t\t\tthis._low = 1\n\t\t\tthis._high = 0\n\t\t\treturn this\n\t\t}\n\n\t\t// Shift the divisor left until it is higher than the dividend\n\t\tvar _other = other.clone()\n\t\tvar i = -1\n\t\twhile ( !this.lt(_other) ) {\n\t\t\t// High bit can overflow the default 16bits\n\t\t\t// Its ok since we right shift after this loop\n\t\t\t// The overflown bit must be kept though\n\t\t\t_other.shiftLeft(1, true)\n\t\t\ti++\n\t\t}\n\n\t\t// Set the remainder\n\t\tthis.remainder = this.clone()\n\t\t// Initialize the current result to 0\n\t\tthis._low = 0\n\t\tthis._high = 0\n\t\tfor (; i >= 0; i--) {\n\t\t\t_other.shiftRight(1)\n\t\t\t// If shifted divisor is smaller than the dividend\n\t\t\t// then subtract it from the dividend\n\t\t\tif ( !this.remainder.lt(_other) ) {\n\t\t\t\tthis.remainder.subtract(_other)\n\t\t\t\t// Update the current result\n\t\t\t\tif (i >= 16) {\n\t\t\t\t\tthis._high |= 1 << (i - 16)\n\t\t\t\t} else {\n\t\t\t\t\tthis._low |= 1 << i\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Negate the current _UINT32_\n\t * @method negate\n\t * @return ThisExpression\n\t */\n\tUINT32.prototype.negate = function () {\n\t\tvar v = ( ~this._low & 0xFFFF ) + 1\n\t\tthis._low = v & 0xFFFF\n\t\tthis._high = (~this._high + (v >>> 16)) & 0xFFFF\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Equals\n\t * @method eq\n\t * @param {Object} other UINT32\n\t * @return {Boolean}\n\t */\n\tUINT32.prototype.equals = UINT32.prototype.eq = function (other) {\n\t\treturn (this._low == other._low) && (this._high == other._high)\n\t}\n\n\t/**\n\t * Greater than (strict)\n\t * @method gt\n\t * @param {Object} other UINT32\n\t * @return {Boolean}\n\t */\n\tUINT32.prototype.greaterThan = UINT32.prototype.gt = function (other) {\n\t\tif (this._high > other._high) return true\n\t\tif (this._high < other._high) return false\n\t\treturn this._low > other._low\n\t}\n\n\t/**\n\t * Less than (strict)\n\t * @method lt\n\t * @param {Object} other UINT32\n\t * @return {Boolean}\n\t */\n\tUINT32.prototype.lessThan = UINT32.prototype.lt = function (other) {\n\t\tif (this._high < other._high) return true\n\t\tif (this._high > other._high) return false\n\t\treturn this._low < other._low\n\t}\n\n\t/**\n\t * Bitwise OR\n\t * @method or\n\t * @param {Object} other UINT32\n\t * @return ThisExpression\n\t */\n\tUINT32.prototype.or = function (other) {\n\t\tthis._low |= other._low\n\t\tthis._high |= other._high\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Bitwise AND\n\t * @method and\n\t * @param {Object} other UINT32\n\t * @return ThisExpression\n\t */\n\tUINT32.prototype.and = function (other) {\n\t\tthis._low &= other._low\n\t\tthis._high &= other._high\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Bitwise NOT\n\t * @method not\n\t * @return ThisExpression\n\t */\n\tUINT32.prototype.not = function() {\n\t\tthis._low = ~this._low & 0xFFFF\n\t\tthis._high = ~this._high & 0xFFFF\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Bitwise XOR\n\t * @method xor\n\t * @param {Object} other UINT32\n\t * @return ThisExpression\n\t */\n\tUINT32.prototype.xor = function (other) {\n\t\tthis._low ^= other._low\n\t\tthis._high ^= other._high\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Bitwise shift right\n\t * @method shiftRight\n\t * @param {Number} number of bits to shift\n\t * @return ThisExpression\n\t */\n\tUINT32.prototype.shiftRight = UINT32.prototype.shiftr = function (n) {\n\t\tif (n > 16) {\n\t\t\tthis._low = this._high >> (n - 16)\n\t\t\tthis._high = 0\n\t\t} else if (n == 16) {\n\t\t\tthis._low = this._high\n\t\t\tthis._high = 0\n\t\t} else {\n\t\t\tthis._low = (this._low >> n) | ( (this._high << (16-n)) & 0xFFFF )\n\t\t\tthis._high >>= n\n\t\t}\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Bitwise shift left\n\t * @method shiftLeft\n\t * @param {Number} number of bits to shift\n\t * @param {Boolean} allow overflow\n\t * @return ThisExpression\n\t */\n\tUINT32.prototype.shiftLeft = UINT32.prototype.shiftl = function (n, allowOverflow) {\n\t\tif (n > 16) {\n\t\t\tthis._high = this._low << (n - 16)\n\t\t\tthis._low = 0\n\t\t\tif (!allowOverflow) {\n\t\t\t\tthis._high &= 0xFFFF\n\t\t\t}\n\t\t} else if (n == 16) {\n\t\t\tthis._high = this._low\n\t\t\tthis._low = 0\n\t\t} else {\n\t\t\tthis._high = (this._high << n) | (this._low >> (16-n))\n\t\t\tthis._low = (this._low << n) & 0xFFFF\n\t\t\tif (!allowOverflow) {\n\t\t\t\t// Overflow only allowed on the high bits...\n\t\t\t\tthis._high &= 0xFFFF\n\t\t\t}\n\t\t}\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Bitwise rotate left\n\t * @method rotl\n\t * @param {Number} number of bits to rotate\n\t * @return ThisExpression\n\t */\n\tUINT32.prototype.rotateLeft = UINT32.prototype.rotl = function (n) {\n\t\tvar v = (this._high << 16) | this._low\n\t\tv = (v << n) | (v >>> (32 - n))\n\t\tthis._low = v & 0xFFFF\n\t\tthis._high = v >>> 16\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Bitwise rotate right\n\t * @method rotr\n\t * @param {Number} number of bits to rotate\n\t * @return ThisExpression\n\t */\n\tUINT32.prototype.rotateRight = UINT32.prototype.rotr = function (n) {\n\t\tvar v = (this._high << 16) | this._low\n\t\tv = (v >>> n) | (v << (32 - n))\n\t\tthis._low = v & 0xFFFF\n\t\tthis._high = v >>> 16\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Clone the current _UINT32_\n\t * @method clone\n\t * @return {Object} cloned UINT32\n\t */\n\tUINT32.prototype.clone = function () {\n\t\treturn new UINT32(this._low, this._high)\n\t}\n\n\tif (typeof define != 'undefined' && define.amd) {\n\t\t// AMD / RequireJS\n\t\tdefine([], function () {\n\t\t\treturn UINT32\n\t\t})\n\t} else if (typeof module != 'undefined' && module.exports) {\n\t\t// Node.js\n\t\tmodule.exports = UINT32\n\t} else {\n\t\t// Browser\n\t\troot['UINT32'] = UINT32\n\t}\n\n})(this)\n","/**\n\tC-like unsigned 64 bits integers in Javascript\n\tCopyright (C) 2013, Pierre Curto\n\tMIT license\n */\n;(function (root) {\n\n\t// Local cache for typical radices\n\tvar radixPowerCache = {\n\t\t16: UINT64( Math.pow(16, 5) )\n\t,\t10: UINT64( Math.pow(10, 5) )\n\t,\t2: UINT64( Math.pow(2, 5) )\n\t}\n\tvar radixCache = {\n\t\t16: UINT64(16)\n\t,\t10: UINT64(10)\n\t,\t2: UINT64(2)\n\t}\n\n\t/**\n\t *\tRepresents an unsigned 64 bits integer\n\t * @constructor\n\t * @param {Number} first low bits (8)\n\t * @param {Number} second low bits (8)\n\t * @param {Number} first high bits (8)\n\t * @param {Number} second high bits (8)\n\t * or\n\t * @param {Number} low bits (32)\n\t * @param {Number} high bits (32)\n\t * or\n\t * @param {String|Number} integer as a string \t\t | integer as a number\n\t * @param {Number|Undefined} radix (optional, default=10)\n\t * @return \n\t */\n\tfunction UINT64 (a00, a16, a32, a48) {\n\t\tif ( !(this instanceof UINT64) )\n\t\t\treturn new UINT64(a00, a16, a32, a48)\n\n\t\tthis.remainder = null\n\t\tif (typeof a00 == 'string')\n\t\t\treturn fromString.call(this, a00, a16)\n\n\t\tif (typeof a16 == 'undefined')\n\t\t\treturn fromNumber.call(this, a00)\n\n\t\tfromBits.apply(this, arguments)\n\t}\n\n\t/**\n\t * Set the current _UINT64_ object with its low and high bits\n\t * @method fromBits\n\t * @param {Number} first low bits (8)\n\t * @param {Number} second low bits (8)\n\t * @param {Number} first high bits (8)\n\t * @param {Number} second high bits (8)\n\t * or\n\t * @param {Number} low bits (32)\n\t * @param {Number} high bits (32)\n\t * @return ThisExpression\n\t */\n\tfunction fromBits (a00, a16, a32, a48) {\n\t\tif (typeof a32 == 'undefined') {\n\t\t\tthis._a00 = a00 & 0xFFFF\n\t\t\tthis._a16 = a00 >>> 16\n\t\t\tthis._a32 = a16 & 0xFFFF\n\t\t\tthis._a48 = a16 >>> 16\n\t\t\treturn this\n\t\t}\n\n\t\tthis._a00 = a00 | 0\n\t\tthis._a16 = a16 | 0\n\t\tthis._a32 = a32 | 0\n\t\tthis._a48 = a48 | 0\n\n\t\treturn this\n\t}\n\tUINT64.prototype.fromBits = fromBits\n\n\t/**\n\t * Set the current _UINT64_ object from a number\n\t * @method fromNumber\n\t * @param {Number} number\n\t * @return ThisExpression\n\t */\n\tfunction fromNumber (value) {\n\t\tthis._a00 = value & 0xFFFF\n\t\tthis._a16 = value >>> 16\n\t\tthis._a32 = 0\n\t\tthis._a48 = 0\n\n\t\treturn this\n\t}\n\tUINT64.prototype.fromNumber = fromNumber\n\n\t/**\n\t * Set the current _UINT64_ object from a string\n\t * @method fromString\n\t * @param {String} integer as a string\n\t * @param {Number} radix (optional, default=10)\n\t * @return ThisExpression\n\t */\n\tfunction fromString (s, radix) {\n\t\tradix = radix || 10\n\n\t\tthis._a00 = 0\n\t\tthis._a16 = 0\n\t\tthis._a32 = 0\n\t\tthis._a48 = 0\n\n\t\t/*\n\t\t\tIn Javascript, bitwise operators only operate on the first 32 bits \n\t\t\tof a number, even though parseInt() encodes numbers with a 53 bits \n\t\t\tmantissa.\n\t\t\tTherefore UINT64(<Number>) can only work on 32 bits.\n\t\t\tThe radix maximum value is 36 (as per ECMA specs) (26 letters + 10 digits)\n\t\t\tmaximum input value is m = 32bits as 1 = 2^32 - 1\n\t\t\tSo the maximum substring length n is:\n\t\t\t36^(n+1) - 1 = 2^32 - 1\n\t\t\t36^(n+1) = 2^32\n\t\t\t(n+1)ln(36) = 32ln(2)\n\t\t\tn = 32ln(2)/ln(36) - 1\n\t\t\tn = 5.189644915687692\n\t\t\tn = 5\n\t\t */\n\t\tvar radixUint = radixPowerCache[radix] || new UINT64( Math.pow(radix, 5) )\n\n\t\tfor (var i = 0, len = s.length; i < len; i += 5) {\n\t\t\tvar size = Math.min(5, len - i)\n\t\t\tvar value = parseInt( s.slice(i, i + size), radix )\n\t\t\tthis.multiply(\n\t\t\t\t\tsize < 5\n\t\t\t\t\t\t? new UINT64( Math.pow(radix, size) )\n\t\t\t\t\t\t: radixUint\n\t\t\t\t)\n\t\t\t\t.add( new UINT64(value) )\n\t\t}\n\n\t\treturn this\n\t}\n\tUINT64.prototype.fromString = fromString\n\n\t/**\n\t * Convert this _UINT64_ to a number (last 32 bits are dropped)\n\t * @method toNumber\n\t * @return {Number} the converted UINT64\n\t */\n\tUINT64.prototype.toNumber = function () {\n\t\treturn (this._a16 * 65536) + this._a00\n\t}\n\n\t/**\n\t * Convert this _UINT64_ to a string\n\t * @method toString\n\t * @param {Number} radix (optional, default=10)\n\t * @return {String} the converted UINT64\n\t */\n\tUINT64.prototype.toString = function (radix) {\n\t\tradix = radix || 10\n\t\tvar radixUint = radixCache[radix] || new UINT64(radix)\n\n\t\tif ( !this.gt(radixUint) ) return this.toNumber().toString(radix)\n\n\t\tvar self = this.clone()\n\t\tvar res = new Array(64)\n\t\tfor (var i = 63; i >= 0; i--) {\n\t\t\tself.div(radixUint)\n\t\t\tres[i] = self.remainder.toNumber().toString(radix)\n\t\t\tif ( !self.gt(radixUint) ) break\n\t\t}\n\t\tres[i-1] = self.toNumber().toString(radix)\n\n\t\treturn res.join('')\n\t}\n\n\t/**\n\t * Add two _UINT64_. The current _UINT64_ stores the result\n\t * @method add\n\t * @param {Object} other UINT64\n\t * @return ThisExpression\n\t */\n\tUINT64.prototype.add = function (other) {\n\t\tvar a00 = this._a00 + other._a00\n\n\t\tvar a16 = a00 >>> 16\n\t\ta16 += this._a16 + other._a16\n\n\t\tvar a32 = a16 >>> 16\n\t\ta32 += this._a32 + other._a32\n\n\t\tvar a48 = a32 >>> 16\n\t\ta48 += this._a48 + other._a48\n\n\t\tthis._a00 = a00 & 0xFFFF\n\t\tthis._a16 = a16 & 0xFFFF\n\t\tthis._a32 = a32 & 0xFFFF\n\t\tthis._a48 = a48 & 0xFFFF\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Subtract two _UINT64_. The current _UINT64_ stores the result\n\t * @method subtract\n\t * @param {Object} other UINT64\n\t * @return ThisExpression\n\t */\n\tUINT64.prototype.subtract = function (other) {\n\t\treturn this.add( other.clone().negate() )\n\t}\n\n\t/**\n\t * Multiply two _UINT64_. The current _UINT64_ stores the result\n\t * @method multiply\n\t * @param {Object} other UINT64\n\t * @return ThisExpression\n\t */\n\tUINT64.prototype.multiply = function (other) {\n\t\t/*\n\t\t\ta = a00 + a16 + a32 + a48\n\t\t\tb = b00 + b16 + b32 + b48\n\t\t\ta*b = (a00 + a16 + a32 + a48)(b00 + b16 + b32 + b48)\n\t\t\t\t= a00b00 + a00b16 + a00b32 + a00b48\n\t\t\t\t+ a16b00 + a16b16 + a16b32 + a16b48\n\t\t\t\t+ a32b00 + a32b16 + a32b32 + a32b48\n\t\t\t\t+ a48b00 + a48b16 + a48b32 + a48b48\n\n\t\t\ta16b48, a32b32, a48b16, a48b32 and a48b48 overflow the 64 bits\n\t\t\tso it comes down to:\n\t\t\ta*b\t= a00b00 + a00b16 + a00b32 + a00b48\n\t\t\t\t+ a16b00 + a16b16 + a16b32\n\t\t\t\t+ a32b00 + a32b16\n\t\t\t\t+ a48b00\n\t\t\t\t= a00b00\n\t\t\t\t+ a00b16 + a16b00\n\t\t\t\t+ a00b32 + a16b16 + a32b00\n\t\t\t\t+ a00b48 + a16b32 + a32b16 + a48b00\n\t\t */\n\t\tvar a00 = this._a00\n\t\tvar a16 = this._a16\n\t\tvar a32 = this._a32\n\t\tvar a48 = this._a48\n\t\tvar b00 = other._a00\n\t\tvar b16 = other._a16\n\t\tvar b32 = other._a32\n\t\tvar b48 = other._a48\n\n\t\tvar c00 = a00 * b00\n\n\t\tvar c16 = c00 >>> 16\n\t\tc16 += a00 * b16\n\t\tvar c32 = c16 >>> 16\n\t\tc16 &= 0xFFFF\n\t\tc16 += a16 * b00\n\n\t\tc32 += c16 >>> 16\n\t\tc32 += a00 * b32\n\t\tvar c48 = c32 >>> 16\n\t\tc32 &= 0xFFFF\n\t\tc32 += a16 * b16\n\t\tc48 += c32 >>> 16\n\t\tc32 &= 0xFFFF\n\t\tc32 += a32 * b00\n\n\t\tc48 += c32 >>> 16\n\t\tc48 += a00 * b48\n\t\tc48 &= 0xFFFF\n\t\tc48 += a16 * b32\n\t\tc48 &= 0xFFFF\n\t\tc48 += a32 * b16\n\t\tc48 &= 0xFFFF\n\t\tc48 += a48 * b00\n\n\t\tthis._a00 = c00 & 0xFFFF\n\t\tthis._a16 = c16 & 0xFFFF\n\t\tthis._a32 = c32 & 0xFFFF\n\t\tthis._a48 = c48 & 0xFFFF\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Divide two _UINT64_. The current _UINT64_ stores the result.\n\t * The remainder is made available as the _remainder_ property on\n\t * the _UINT64_ object. It can be null, meaning there are no remainder.\n\t * @method div\n\t * @param {Object} other UINT64\n\t * @return ThisExpression\n\t */\n\tUINT64.prototype.div = function (other) {\n\t\tif ( (other._a16 == 0) && (other._a32 == 0) && (other._a48 == 0) ) {\n\t\t\tif (other._a00 == 0) throw Error('division by zero')\n\n\t\t\t// other == 1: this\n\t\t\tif (other._a00 == 1) {\n\t\t\t\tthis.remainder = new UINT64(0)\n\t\t\t\treturn this\n\t\t\t}\n\t\t}\n\n\t\t// other > this: 0\n\t\tif ( other.gt(this) ) {\n\t\t\tthis.remainder = this.clone()\n\t\t\tthis._a00 = 0\n\t\t\tthis._a16 = 0\n\t\t\tthis._a32 = 0\n\t\t\tthis._a48 = 0\n\t\t\treturn this\n\t\t}\n\t\t// other == this: 1\n\t\tif ( this.eq(other) ) {\n\t\t\tthis.remainder = new UINT64(0)\n\t\t\tthis._a00 = 1\n\t\t\tthis._a16 = 0\n\t\t\tthis._a32 = 0\n\t\t\tthis._a48 = 0\n\t\t\treturn this\n\t\t}\n\n\t\t// Shift the divisor left until it is higher than the dividend\n\t\tvar _other = other.clone()\n\t\tvar i = -1\n\t\twhile ( !this.lt(_other) ) {\n\t\t\t// High bit can overflow the default 16bits\n\t\t\t// Its ok since we right shift after this loop\n\t\t\t// The overflown bit must be kept though\n\t\t\t_other.shiftLeft(1, true)\n\t\t\ti++\n\t\t}\n\n\t\t// Set the remainder\n\t\tthis.remainder = this.clone()\n\t\t// Initialize the current result to 0\n\t\tthis._a00 = 0\n\t\tthis._a16 = 0\n\t\tthis._a32 = 0\n\t\tthis._a48 = 0\n\t\tfor (; i >= 0; i--) {\n\t\t\t_other.shiftRight(1)\n\t\t\t// If shifted divisor is smaller than the dividend\n\t\t\t// then subtract it from the dividend\n\t\t\tif ( !this.remainder.lt(_other) ) {\n\t\t\t\tthis.remainder.subtract(_other)\n\t\t\t\t// Update the current result\n\t\t\t\tif (i >= 48) {\n\t\t\t\t\tthis._a48 |= 1 << (i - 48)\n\t\t\t\t} else if (i >= 32) {\n\t\t\t\t\tthis._a32 |= 1 << (i - 32)\n\t\t\t\t} else if (i >= 16) {\n\t\t\t\t\tthis._a16 |= 1 << (i - 16)\n\t\t\t\t} else {\n\t\t\t\t\tthis._a00 |= 1 << i\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Negate the current _UINT64_\n\t * @method negate\n\t * @return ThisExpression\n\t */\n\tUINT64.prototype.negate = function () {\n\t\tvar v = ( ~this._a00 & 0xFFFF ) + 1\n\t\tthis._a00 = v & 0xFFFF\n\t\tv = (~this._a16 & 0xFFFF) + (v >>> 16)\n\t\tthis._a16 = v & 0xFFFF\n\t\tv = (~this._a32 & 0xFFFF) + (v >>> 16)\n\t\tthis._a32 = v & 0xFFFF\n\t\tthis._a48 = (~this._a48 + (v >>> 16)) & 0xFFFF\n\n\t\treturn this\n\t}\n\n\t/**\n\n\t * @method eq\n\t * @param {Object} other UINT64\n\t * @return {Boolean}\n\t */\n\tUINT64.prototype.equals = UINT64.prototype.eq = function (other) {\n\t\treturn (this._a48 == other._a48) && (this._a00 == other._a00)\n\t\t\t && (this._a32 == other._a32) && (this._a16 == other._a16)\n\t}\n\n\t/**\n\t * Greater than (strict)\n\t * @method gt\n\t * @param {Object} other UINT64\n\t * @return {Boolean}\n\t */\n\tUINT64.prototype.greaterThan = UINT64.prototype.gt = function (other) {\n\t\tif (this._a48 > other._a48) return true\n\t\tif (this._a48 < other._a48) return false\n\t\tif (this._a32 > other._a32) return true\n\t\tif (this._a32 < other._a32) return false\n\t\tif (this._a16 > other._a16) return true\n\t\tif (this._a16 < other._a16) return false\n\t\treturn this._a00 > other._a00\n\t}\n\n\t/**\n\t * Less than (strict)\n\t * @method lt\n\t * @param {Object} other UINT64\n\t * @return {Boolean}\n\t */\n\tUINT64.prototype.lessThan = UINT64.prototype.lt = function (other) {\n\t\tif (this._a48 < other._a48) return true\n\t\tif (this._a48 > other._a48) return false\n\t\tif (this._a32 < other._a32) return true\n\t\tif (this._a32 > other._a32) return false\n\t\tif (this._a16 < other._a16) return true\n\t\tif (this._a16 > other._a16) return false\n\t\treturn this._a00 < other._a00\n\t}\n\n\t/**\n\t * Bitwise OR\n\t * @method or\n\t * @param {Object} other UINT64\n\t * @return ThisExpression\n\t */\n\tUINT64.prototype.or = function (other) {\n\t\tthis._a00 |= other._a00\n\t\tthis._a16 |= other._a16\n\t\tthis._a32 |= other._a32\n\t\tthis._a48 |= other._a48\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Bitwise AND\n\t * @method and\n\t * @param {Object} other UINT64\n\t * @return ThisExpression\n\t */\n\tUINT64.prototype.and = function (other) {\n\t\tthis._a00 &= other._a00\n\t\tthis._a16 &= other._a16\n\t\tthis._a32 &= other._a32\n\t\tthis._a48 &= other._a48\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Bitwise XOR\n\t * @method xor\n\t * @param {Object} other UINT64\n\t * @return ThisExpression\n\t */\n\tUINT64.prototype.xor = function (other) {\n\t\tthis._a00 ^= other._a00\n\t\tthis._a16 ^= other._a16\n\t\tthis._a32 ^= other._a32\n\t\tthis._a48 ^= other._a48\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Bitwise NOT\n\t * @method not\n\t * @return ThisExpression\n\t */\n\tUINT64.prototype.not = function() {\n\t\tthis._a00 = ~this._a00 & 0xFFFF\n\t\tthis._a16 = ~this._a16 & 0xFFFF\n\t\tthis._a32 = ~this._a32 & 0xFFFF\n\t\tthis._a48 = ~this._a48 & 0xFFFF\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Bitwise shift right\n\t * @method shiftRight\n\t * @param {Number} number of bits to shift\n\t * @return ThisExpression\n\t */\n\tUINT64.prototype.shiftRight = UINT64.prototype.shiftr = function (n) {\n\t\tn %= 64\n\t\tif (n >= 48) {\n\t\t\tthis._a00 = this._a48 >> (n - 48)\n\t\t\tthis._a16 = 0\n\t\t\tthis._a32 = 0\n\t\t\tthis._a48 = 0\n\t\t} else if (n >= 32) {\n\t\t\tn -= 32\n\t\t\tthis._a00 = ( (this._a32 >> n) | (this._a48 << (16-n)) ) & 0xFFFF\n\t\t\tthis._a16 = (this._a48 >> n) & 0xFFFF\n\t\t\tthis._a32 = 0\n\t\t\tthis._a48 = 0\n\t\t} else if (n >= 16) {\n\t\t\tn -= 16\n\t\t\tthis._a00 = ( (this._a16 >> n) | (this._a32 << (16-n)) ) & 0xFFFF\n\t\t\tthis._a16 = ( (this._a32 >> n) | (this._a48 << (16-n)) ) & 0xFFFF\n\t\t\tthis._a32 = (this._a48 >> n) & 0xFFFF\n\t\t\tthis._a48 = 0\n\t\t} else {\n\t\t\tthis._a00 = ( (this._a00 >> n) | (this._a16 << (16-n)) ) & 0xFFFF\n\t\t\tthis._a16 = ( (this._a16 >> n) | (this._a32 << (16-n)) ) & 0xFFFF\n\t\t\tthis._a32 = ( (this._a32 >> n) | (this._a48 << (16-n)) ) & 0xFFFF\n\t\t\tthis._a48 = (this._a48 >> n) & 0xFFFF\n\t\t}\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Bitwise shift left\n\t * @method shiftLeft\n\t * @param {Number} number of bits to shift\n\t * @param {Boolean} allow overflow\n\t * @return ThisExpression\n\t */\n\tUINT64.prototype.shiftLeft = UINT64.prototype.shiftl = function (n, allowOverflow) {\n\t\tn %= 64\n\t\tif (n >= 48) {\n\t\t\tthis._a48 = this._a00 << (n - 48)\n\t\t\tthis._a32 = 0\n\t\t\tthis._a16 = 0\n\t\t\tthis._a00 = 0\n\t\t} else if (n >= 32) {\n\t\t\tn -= 32\n\t\t\tthis._a48 = (this._a16 << n) | (this._a00 >> (16-n))\n\t\t\tthis._a32 = (this._a00 << n) & 0xFFFF\n\t\t\tthis._a16 = 0\n\t\t\tthis._a00 = 0\n\t\t} else if (n >= 16) {\n\t\t\tn -= 16\n\t\t\tthis._a48 = (this._a32 << n) | (this._a16 >> (16-n))\n\t\t\tthis._a32 = ( (this._a16 << n) | (this._a00 >> (16-n)) ) & 0xFFFF\n\t\t\tthis._a16 = (this._a00 << n) & 0xFFFF\n\t\t\tthis._a00 = 0\n\t\t} else {\n\t\t\tthis._a48 = (this._a48 << n) | (this._a32 >> (16-n))\n\t\t\tthis._a32 = ( (this._a32 << n) | (this._a16 >> (16-n)) ) & 0xFFFF\n\t\t\tthis._a16 = ( (this._a16 << n) | (this._a00 >> (16-n)) ) & 0xFFFF\n\t\t\tthis._a00 = (this._a00 << n) & 0xFFFF\n\t\t}\n\t\tif (!allowOverflow) {\n\t\t\tthis._a48 &= 0xFFFF\n\t\t}\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Bitwise rotate left\n\t * @method rotl\n\t * @param {Number} number of bits to rotate\n\t * @return ThisExpression\n\t */\n\tUINT64.prototype.rotateLeft = UINT64.prototype.rotl = function (n) {\n\t\tn %= 64\n\t\tif (n == 0) return this\n\t\tif (n >= 32) {\n\t\t\t// A.B.C.D\n\t\t\t// B.C.D.A rotl(16)\n\t\t\t// C.D.A.B rotl(32)\n\t\t\tvar v = this._a00\n\t\t\tthis._a00 = this._a32\n\t\t\tthis._a32 = v\n\t\t\tv = this._a48\n\t\t\tthis._a48 = this._a16\n\t\t\tthis._a16 = v\n\t\t\tif (n == 32) return this\n\t\t\tn -= 32\n\t\t}\n\n\t\tvar high = (this._a48 << 16) | this._a32\n\t\tvar low = (this._a16 << 16) | this._a00\n\n\t\tvar _high = (high << n) | (low >>> (32 - n))\n\t\tvar _low = (low << n) | (high >>> (32 - n))\n\n\t\tthis._a00 = _low & 0xFFFF\n\t\tthis._a16 = _low >>> 16\n\t\tthis._a32 = _high & 0xFFFF\n\t\tthis._a48 = _high >>> 16\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Bitwise rotate right\n\t * @method rotr\n\t * @param {Number} number of bits to rotate\n\t * @return ThisExpression\n\t */\n\tUINT64.prototype.rotateRight = UINT64.prototype.rotr = function (n) {\n\t\tn %= 64\n\t\tif (n == 0) return this\n\t\tif (n >= 32) {\n\t\t\t// A.B.C.D\n\t\t\t// D.A.B.C rotr(16)\n\t\t\t// C.D.A.B rotr(32)\n\t\t\tvar v = this._a00\n\t\t\tthis._a00 = this._a32\n\t\t\tthis._a32 = v\n\t\t\tv = this._a48\n\t\t\tthis._a48 = this._a16\n\t\t\tthis._a16 = v\n\t\t\tif (n == 32) return this\n\t\t\tn -= 32\n\t\t}\n\n\t\tvar high = (this._a48 << 16) | this._a32\n\t\tvar low = (this._a16 << 16) | this._a00\n\n\t\tvar _high = (high >>> n) | (low << (32 - n))\n\t\tvar _low = (low >>> n) | (high << (32 - n))\n\n\t\tthis._a00 = _low & 0xFFFF\n\t\tthis._a16 = _low >>> 16\n\t\tthis._a32 = _high & 0xFFFF\n\t\tthis._a48 = _high >>> 16\n\n\t\treturn this\n\t}\n\n\t/**\n\t * Clone the current _UINT64_\n\t * @method clone\n\t * @return {Object} cloned UINT64\n\t */\n\tUINT64.prototype.clone = function () {\n\t\treturn new UINT64(this._a00, this._a16, this._a32, this._a48)\n\t}\n\n\tif (typeof define != 'undefined' && define.amd) {\n\t\t// AMD / RequireJS\n\t\tdefine([], function () {\n\t\t\treturn UINT64\n\t\t})\n\t} else if (typeof module != 'undefined' && module.exports) {\n\t\t// Node.js\n\t\tmodule.exports = UINT64\n\t} else {\n\t\t// Browser\n\t\troot['UINT64'] = UINT64\n\t}\n\n})(this)\n","exports.UINT32 = require('./lib/uint32')\nexports.UINT64 = require('./lib/uint64')","/**\nxxHash implementation in pure Javascript\n\nCopyright (C) 2013, Pierre Curto\nMIT license\n*/\nvar UINT32 = require('cuint').UINT32\n\n/*\n\tMerged this sequence of method calls as it speeds up\n\tthe calculations by a factor of 2\n */\n// this.v1.add( other.multiply(PRIME32_2) ).rotl(13).multiply(PRIME32_1);\nUINT32.prototype.xxh_update = function (low, high) {\n\tvar b00 = PRIME32_2._low\n\tvar b16 = PRIME32_2._high\n\n\tvar c16, c00\n\tc00 = low * b00\n\tc16 = c00 >>> 16\n\n\tc16 += high * b00\n\tc16 &= 0xFFFF\t\t// Not required but improves performance\n\tc16 += low * b16\n\n\tvar a00 = this._low + (c00 & 0xFFFF)\n\tvar a16 = a00 >>> 16\n\n\ta16 += this._high + (c16 & 0xFFFF)\n\n\tvar v = (a16 << 16) | (a00 & 0xFFFF)\n\tv = (v << 13) | (v >>> 19)\n\n\ta00 = v & 0xFFFF\n\ta16 = v >>> 16\n\n\tb00 = PRIME32_1._low\n\tb16 = PRIME32_1._high\n\n\tc00 = a00 * b00\n\tc16 = c00 >>> 16\n\n\tc16 += a16 * b00\n\tc16 &= 0xFFFF\t\t// Not required but improves performance\n\tc16 += a00 * b16\n\n\tthis._low = c00 & 0xFFFF\n\tthis._high = c16 & 0xFFFF\n}\n\n/*\n * Constants\n */\nvar PRIME32_1 = UINT32( '2654435761' )\nvar PRIME32_2 = UINT32( '2246822519' )\nvar PRIME32_3 = UINT32( '3266489917' )\nvar PRIME32_4 = UINT32( '668265263' )\nvar PRIME32_5 = UINT32( '374761393' )\n\n/**\n* Convert string to proper UTF-8 array\n* @param str Input string\n* @returns {Uint8Array} UTF8 array is returned as uint8 array\n*/\nfunction toUTF8Array (str) {\n\tvar utf8 = []\n\tfor (var i=0, n=str.length; i < n; i++) {\n\t\tvar charcode = str.charCodeAt(i)\n\t\tif (charcode < 0x80) utf8.push(charcode)\n\t\telse if (charcode < 0x800) {\n\t\t\tutf8.push(0xc0 | (charcode >> 6),\n\t\t\t0x80 | (charcode & 0x3f))\n\t\t}\n\t\telse if (charcode < 0xd800 || charcode >= 0xe000) {\n\t\t\tutf8.push(0xe0 | (charcode >> 12),\n\t\t\t0x80 | ((charcode>>6) & 0x3f),\n\t\t\t0x80 | (charcode & 0x3f))\n\t\t}\n\t\t// surrogate pair\n\t\telse {\n\t\t\ti++;\n\t\t\t// UTF-16 encodes 0x10000-0x10FFFF by\n\t\t\t// subtracting 0x10000 and splitting the\n\t\t\t// 20 bits of 0x0-0xFFFFF into two halves\n\t\t\tcharcode = 0x10000 + (((charcode & 0x3ff)<<10)\n\t\t\t| (str.charCodeAt(i) & 0x3ff))\n\t\t\tutf8.push(0xf0 | (charcode >>18),\n\t\t\t0x80 | ((charcode>>12) & 0x3f),\n\t\t\t0x80 | ((charcode>>6) & 0x3f),\n\t\t\t0x80 | (charcode & 0x3f))\n\t\t}\n\t}\n\n\treturn new Uint8Array(utf8)\n}\n\n/**\n * XXH object used as a constructor or a function\n * @constructor\n * or\n * @param {Object|String} input data\n * @param {Number|UINT32} seed\n * @return ThisExpression\n * or\n * @return {UINT32} xxHash\n */\nfunction XXH () {\n\tif (arguments.length == 2)\n\t\treturn new XXH( arguments[1] ).update( arguments[0] ).digest()\n\n\tif (!(this instanceof XXH))\n\t\treturn new XXH( arguments[0] )\n\n\tinit.call(this, arguments[0])\n}\n\n/**\n * Initialize the XXH instance with the given seed\n * @method init\n * @param {Number|Object} seed as a number or an unsigned 32 bits integer\n * @return ThisExpression\n */\n function init (seed) {\n\tthis.seed = seed instanceof UINT32 ? seed.clone() : UINT32(seed)\n\tthis.v1 = this.seed.clone().add(PRIME32_1).add(PRIME32_2)\n\tthis.v2 = this.seed.clone().add(PRIME32_2)\n\tthis.v3 = this.seed.clone()\n\tthis.v4 = this.seed.clone().subtract(PRIME32_1)\n\tthis.total_len = 0\n\tthis.memsize = 0\n\tthis.memory = null\n\n\treturn this\n}\nXXH.prototype.init = init\n\n/**\n * Add data to be computed for the XXH hash\n * @method update\n * @param {String|Buffer|ArrayBuffer} input as a string or nodejs Buffer or ArrayBuffer\n * @return ThisExpression\n */\nXXH.prototype.update = function (input) {\n\tvar isString = typeof input == 'string'\n\tvar isArrayBuffer\n\n\t// Convert all strings to utf-8 first (issue #5)\n\tif (isString) {\n\t\tinput = toUTF8Array(input)\n\t\tisString = false\n\t\tisArrayBuffer = true\n\t}\n\n\tif (typeof ArrayBuffer !== \"undefined\" && input instanceof ArrayBuffer)\n\t{\n\t\tisArrayBuffer = true\n\t\tinput = new Uint8Array(input);\n\t}\n\n\tvar p = 0\n\tvar len = input.length\n\tvar bEnd = p + len\n\n\tif (len == 0) return this\n\n\tthis.total_len += len\n\n\tif (this.memsize == 0)\n\t{\n\t\tif (isString) {\n\t\t\tthis.memory = ''\n\t\t} else if (isArrayBuffer) {\n\t\t\tthis.memory = new Uint8Array(16)\n\t\t} else {\n\t\t\tthis.memory = new Buffer(16)\n\t\t}\n\t}\n\n\tif (this.memsize + len < 16) // fill in tmp buffer\n\t{\n\t\t// XXH_memcpy(this.memory + this.memsize, input, len)\n\t\tif (isString) {\n\t\t\tthis.memory += input\n\t\t} else if (isArrayBuffer) {\n\t\t\tthis.memory.set( input.subarray(0, len), this.memsize )\n\t\t} else {\n\t\t\tinput.copy( this.memory, this.memsize, 0, len )\n\t\t}\n\n\t\tthis.memsize += len\n\t\treturn this\n\t}\n\n\tif (this.memsize > 0) // some data left from previous update\n\t{\n\t\t// XXH_memcpy(this.memory + this.memsize, input, 16-this.memsize);\n\t\tif (isString) {\n\t\t\tthis.memory += input.slice(0, 16 - this.memsize)\n\t\t} else if (isArrayBuffer) {\n\t\t\tthis.memory.set( input.subarray(0, 16 - this.memsize), this.memsize )\n\t\t} else {\n\t\t\tinput.copy( this.memory, this.memsize, 0, 16 - this.memsize )\n\t\t}\n\n\t\tvar p32 = 0\n\t\tif (isString) {\n\t\t\tthis.v1.xxh_update(\n\t\t\t\t(this.memory.charCodeAt(p32+1) << 8) | this.memory.charCodeAt(p32)\n\t\t\t,\t(this.memory.charCodeAt(p32+3) << 8) | this.memory.charCodeAt(p32+2)\n\t\t\t)\n\t\t\tp32 += 4\n\t\t\tthis.v2.xxh_update(\n\t\t\t\t(this.memory.charCodeAt(p32+1) << 8) | this.memory.charCodeAt(p32)\n\t\t\t,\t(this.memory.charCodeAt(p32+3) << 8) | this.memory.charCodeAt(p32+2)\n\t\t\t)\n\t\t\tp32 += 4\n\t\t\tthis.v3.xxh_update(\n\t\t\t\t(this.memory.charCodeAt(p32+1) << 8) | this.memory.charCodeAt(p32)\n\t\t\t,\t(this.memory.charCodeAt(p32+3) << 8) | this.memory.charCodeAt(p32+2)\n\t\t\t)\n\t\t\tp32 += 4\n\t\t\tthis.v4.xxh_update(\n\t\t\t\t(this.memory.charCodeAt(p32+1) << 8) | this.memory.charCodeAt(p32)\n\t\t\t,\t(this.memory.charCodeAt(p32+3) << 8) | this.memory.charCodeAt(p32+2)\n\t\t\t)\n\t\t} else {\n\t\t\tthis.v1.xxh_update(\n\t\t\t\t(this.memory[p32+1] << 8) | this.memory[p32]\n\t\t\t,\t(this.memory[p32+3] << 8) | this.memory[p32+2]\n\t\t\t)\n\t\t\tp32 += 4\n\t\t\tthis.v2.xxh_update(\n\t\t\t\t(this.memory[p32+1] << 8) | this.memory[p32]\n\t\t\t,\t(this.memory[p32+3] << 8) | this.memory[p32+2]\n\t\t\t)\n\t\t\tp32 += 4\n\t\t\tthis.v3.xxh_update(\n\t\t\t\t(this.memory[p32+1] << 8) | this.memory[p32]\n\t\t\t,\t(this.memory[p32+3] << 8) | this.memory[p32+2]\n\t\t\t)\n\t\t\tp32 += 4\n\t\t\tthis.v4.xxh_update(\n\t\t\t\t(this.memory[p32+1] << 8) | this.memory[p32]\n\t\t\t,\t(this.memory[p32+3] << 8) | this.memory[p32+2]\n\t\t\t)\n\t\t}\n\n\t\tp += 16 - this.memsize\n\t\tthis.memsize = 0\n\t\tif (isString) this.memory = ''\n\t}\n\n\tif (p <= bEnd - 16)\n\t{\n\t\tvar limit = bEnd - 16\n\n\t\tdo\n\t\t{\n\t\t\tif (isString) {\n\t\t\t\tthis.v1.xxh_update(\n\t\t\t\t\t(input.charCodeAt(p+1) << 8) | input.charCodeAt(p)\n\t\t\t\t,\t(input.charCodeAt(p+3) << 8) | input.charCodeAt(p+2)\n\t\t\t\t)\n\t\t\t\tp += 4\n\t\t\t\tthis.v2.xxh_update(\n\t\t\t\t\t(input.charCodeAt(p+1) << 8) | input.charCodeAt(p)\n\t\t\t\t,\t(input.charCodeAt(p+3) << 8) | input.charCodeAt(p+2)\n\t\t\t\t)\n\t\t\t\tp += 4\n\t\t\t\tthis.v3.xxh_update(\n\t\t\t\t\t(input.charCodeAt(p+1) << 8) | input.charCodeAt(p)\n\t\t\t\t,\t(input.charCodeAt(p+3) << 8) | input.charCodeAt(p+2)\n\t\t\t\t)\n\t\t\t\tp += 4\n\t\t\t\tthis.v4.xxh_update(\n\t\t\t\t\t(input.charCodeAt(p+1) << 8) | input.charCodeAt(p)\n\t\t\t\t,\t(input.charCodeAt(p+3) << 8) | input.charCodeAt(p+2)\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\tthis.v1.xxh_update(\n\t\t\t\t\t(input[p+1] << 8) | input[p]\n\t\t\t\t,\t(input[p+3] << 8) | input[p+2]\n\t\t\t\t)\n\t\t\t\tp += 4\n\t\t\t\tthis.v2.xxh_update(\n\t\t\t\t\t(input[p+1] << 8) | input[p]\n\t\t\t\t,\t(input[p+3] << 8) | input[p+2]\n\t\t\t\t)\n\t\t\t\tp += 4\n\t\t\t\tthis.v3.xxh_update(\n\t\t\t\t\t(input[p+1] << 8) | input[p]\n\t\t\t\t,\t(input[p+3] << 8) | input[p+2]\n\t\t\t\t)\n\t\t\t\tp += 4\n\t\t\t\tthis.v4.xxh_update(\n\t\t\t\t\t(input[p+1] << 8) | input[p]\n\t\t\t\t,\t(input[p+3] << 8) | input[p+2]\n\t\t\t\t)\n\t\t\t}\n\t\t\tp += 4\n\t\t} while (p <= limit)\n\t}\n\n\tif (p < bEnd)\n\t{\n\t\t// XXH_memcpy(this.memory, p, bEnd-p);\n\t\tif (isString) {\n\t\t\tthis.memory += input.slice(p)\n\t\t} else if (isArrayBuffer) {\n\t\t\tthis.memory.set( input.subarray(p, bEnd), this.memsize )\n\t\t} else {\n\t\t\tinput.copy( this.memory, this.memsize, p, bEnd )\n\t\t}\n\n\t\tthis.memsize = bEnd - p\n\t}\n\n\treturn this\n}\n\n/**\n * Finalize the XXH computation. The XXH instance is ready for reuse for the given seed\n * @method digest\n * @return {UINT32} xxHash\n */\nXXH.prototype.digest = function () {\n\tvar input = this.memory\n\tvar isString = typeof input == 'string'\n\tvar p = 0\n\tvar bEnd = this.memsize\n\tvar h32, h\n\tvar u = new UINT32\n\n\tif (this.total_len >= 16)\n\t{\n\t\th32 = this.v1.rotl(1).add( this.v2.rotl(7).add( this.v3.rotl(12).add( this.v4.rotl(18) ) ) )\n\t}\n\telse\n\t{\n\t\th32 = this.seed.clone().add( PRIME32_5 )\n\t}\n\n\th32.add( u.fromNumber(this.total_len) )\n\n\twhile (p <= bEnd - 4)\n\t{\n\t\tif (isString) {\n\t\t\tu.fromBits(\n\t\t\t\t(input.charCodeAt(p+1) << 8) | input.charCodeAt(p)\n\t\t\t,\t(input.charCodeAt(p+3) << 8) | input.charCodeAt(p+2)\n\t\t\t)\n\t\t} else {\n\t\t\tu.fromBits(\n\t\t\t\t(input[p+1] << 8) | input[p]\n\t\t\t,\t(input[p+3] << 8) | input[p+2]\n\t\t\t)\n\t\t}\n\t\th32\n\t\t\t.add( u.multiply(PRIME32_3) )\n\t\t\t.rotl(17)\n\t\t\t.multiply( PRIME32_4 )\n\t\tp += 4\n\t}\n\n\twhile (p < bEnd)\n\t{\n\t\tu.fromBits( isString ? input.charCodeAt(p++) : input[p++], 0 )\n\t\th32\n\t\t\t.add( u.multiply(PRIME32_5) )\n\t\t\t.rotl(11)\n\t\t\t.multiply(PRIME32_1)\n\t}\n\n\th = h32.clone().shiftRight(15)\n\th32.xor(h).multiply(PRIME32_2)\n\n\th = h32.clone().shiftRight(13)\n\th32.xor(h).multiply(PRIME32_3)\n\n\th = h32.clone().shiftRight(16)\n\th32.xor(h)\n\n\t// Reset the state\n\tthis.init( this.seed )\n\n\treturn h32\n}\n\nmodule.exports = XXH\n","/**\nxxHash64 implementation in pure Javascript\n\nCopyright (C) 2016, Pierre Curto\nMIT license\n*/\nvar UINT64 = require('cuint').UINT64\n\n/*\n * Constants\n */\nvar PRIME64_1 = UINT64( '11400714785074694791' )\nvar PRIME64_2 = UINT64( '14029467366897019727' )\nvar PRIME64_3 = UINT64( '1609587929392839161' )\nvar PRIME64_4 = UINT64( '9650029242287828579' )\nvar PRIME64_5 = UINT64( '2870177450012600261' )\n\n/**\n* Convert string to proper UTF-8 array\n* @param str Input string\n* @returns {Uint8Array} UTF8 array is returned as uint8 array\n*/\nfunction toUTF8Array (str) {\n\tvar utf8 = []\n\tfor (var i=0, n=str.length; i < n; i++) {\n\t\tvar charcode = str.charCodeAt(i)\n\t\tif (charcode < 0x80) utf8.push(charcode)\n\t\telse if (charcode < 0x800) {\n\t\t\tutf8.push(0xc0 | (charcode >> 6),\n\t\t\t0x80 | (charcode & 0x3f))\n\t\t}\n\t\telse if (charcode < 0xd800 || charcode >= 0xe000) {\n\t\t\tutf8.push(0xe0 | (charcode >> 12),\n\t\t\t0x80 | ((charcode>>6) & 0x3f),\n\t\t\t0x80 | (charcode & 0x3f))\n\t\t}\n\t\t// surrogate pair\n\t\telse {\n\t\t\ti++;\n\t\t\t// UTF-16 encodes 0x10000-0x10FFFF by\n\t\t\t// subtracting 0x10000 and splitting the\n\t\t\t// 20 bits of 0x0-0xFFFFF into two halves\n\t\t\tcharcode = 0x10000 + (((charcode & 0x3ff)<<10)\n\t\t\t| (str.charCodeAt(i) & 0x3ff))\n\t\t\tutf8.push(0xf0 | (charcode >>18),\n\t\t\t0x80 | ((charcode>>12) & 0x3f),\n\t\t\t0x80 | ((charcode>>6) & 0x3f),\n\t\t\t0x80 | (charcode & 0x3f))\n\t\t}\n\t}\n\n\treturn new Uint8Array(utf8)\n}\n\n/**\n * XXH64 object used as a constructor or a function\n * @constructor\n * or\n * @param {Object|String} input data\n * @param {Number|UINT64} seed\n * @return ThisExpression\n * or\n * @return {UINT64} xxHash\n */\nfunction XXH64 () {\n\tif (arguments.length == 2)\n\t\treturn new XXH64( arguments[1] ).update( arguments[0] ).digest()\n\n\tif (!(this instanceof XXH64))\n\t\treturn new XXH64( arguments[0] )\n\n\tinit.call(this, arguments[0])\n}\n\n/**\n * Initialize the XXH64 instance with the given seed\n * @method init\n * @param {Number|Object} seed as a number or an unsigned 32 bits integer\n * @return ThisExpression\n */\n function init (seed) {\n\tthis.seed = seed instanceof UINT64 ? seed.clone() : UINT64(seed)\n\tthis.v1 = this.seed.clone().add(PRIME64_1).add(PRIME64_2)\n\tthis.v2 = this.seed.clone().add(PRIME64_2)\n\tthis.v3 = this.seed.clone()\n\tthis.v4 = this.seed.clone().subtract(PRIME64_1)\n\tthis.total_len = 0\n\tthis.memsize = 0\n\tthis.memory = null\n\n\treturn this\n}\nXXH64.prototype.init = init\n\n/**\n * Add data to be computed for the XXH64 hash\n * @method update\n * @param {String|Buffer|ArrayBuffer} input as a string or nodejs Buffer or ArrayBuffer\n * @return ThisExpression\n */\nXXH64.prototype.update = function (input) {\n\tvar isString = typeof input == 'string'\n\tvar isArrayBuffer\n\n\t// Convert all strings to utf-8 first (issue #5)\n\tif (isString) {\n\t\tinput = toUTF8Array(input)\n\t\tisString = false\n\t\tisArrayBuffer = true\n\t}\n\n\tif (typeof ArrayBuffer !== \"undefined\" && input instanceof ArrayBuffer)\n\t{\n\t\tisArrayBuffer = true\n\t\tinput = new Uint8Array(input);\n\t}\n\n\tvar p = 0\n\tvar len = input.length\n\tvar bEnd = p + len\n\n\tif (len == 0) return this\n\n\tthis.total_len += len\n\n\tif (this.memsize == 0)\n\t{\n\t\tif (isString) {\n\t\t\tthis.memory = ''\n\t\t} else if (isArrayBuffer) {\n\t\t\tthis.memory = new Uint8Array(32)\n\t\t} else {\n\t\t\tthis.memory = new Buffer(32)\n\t\t}\n\t}\n\n\tif (this.memsize + len < 32) // fill in tmp buffer\n\t{\n\t\t// XXH64_memcpy(this.memory + this.memsize, input, len)\n\t\tif (isString) {\n\t\t\tthis.memory += input\n\t\t} else if (isArrayBuffer) {\n\t\t\tthis.memory.set( input.subarray(0, len), this.memsize )\n\t\t} else {\n\t\t\tinput.copy( this.memory, this.memsize, 0, len )\n\t\t}\n\n\t\tthis.memsize += len\n\t\treturn this\n\t}\n\n\tif (this.memsize > 0) // some data left from previous update\n\t{\n\t\t// XXH64_memcpy(this.memory + this.memsize, input, 16-this.memsize);\n\t\tif (isString) {\n\t\t\tthis.memory += input.slice(0, 32 - this.memsize)\n\t\t} else if (isArrayBuffer) {\n\t\t\tthis.memory.set( input.subarray(0, 32 - this.memsize), this.memsize )\n\t\t} else {\n\t\t\tinput.copy( this.memory, this.memsize, 0, 32 - this.memsize )\n\t\t}\n\n\t\tvar p64 = 0\n\t\tif (isString) {\n\t\t\tvar other\n\t\t\tother = UINT64(\n\t\t\t\t\t(this.memory.charCodeAt(p64+1) << 8) | this.memory.charCodeAt(p64)\n\t\t\t\t,\t(this.memory.charCodeAt(p64+3) << 8) | this.memory.charCodeAt(p64+2)\n\t\t\t\t,\t(this.memory.charCodeAt(p64+5) << 8) | this.memory.charCodeAt(p64+4)\n\t\t\t\t,\t(this.memory.charCodeAt(p64+7) << 8) | this.memory.charCodeAt(p64+6)\n\t\t\t\t)\n\t\t\tthis.v1.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t\tp64 += 8\n\t\t\tother = UINT64(\n\t\t\t\t\t(this.memory.charCodeAt(p64+1) << 8) | this.memory.charCodeAt(p64)\n\t\t\t\t,\t(this.memory.charCodeAt(p64+3) << 8) | this.memory.charCodeAt(p64+2)\n\t\t\t\t,\t(this.memory.charCodeAt(p64+5) << 8) | this.memory.charCodeAt(p64+4)\n\t\t\t\t,\t(this.memory.charCodeAt(p64+7) << 8) | this.memory.charCodeAt(p64+6)\n\t\t\t\t)\n\t\t\tthis.v2.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t\tp64 += 8\n\t\t\tother = UINT64(\n\t\t\t\t\t(this.memory.charCodeAt(p64+1) << 8) | this.memory.charCodeAt(p64)\n\t\t\t\t,\t(this.memory.charCodeAt(p64+3) << 8) | this.memory.charCodeAt(p64+2)\n\t\t\t\t,\t(this.memory.charCodeAt(p64+5) << 8) | this.memory.charCodeAt(p64+4)\n\t\t\t\t,\t(this.memory.charCodeAt(p64+7) << 8) | this.memory.charCodeAt(p64+6)\n\t\t\t\t)\n\t\t\tthis.v3.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t\tp64 += 8\n\t\t\tother = UINT64(\n\t\t\t\t\t(this.memory.charCodeAt(p64+1) << 8) | this.memory.charCodeAt(p64)\n\t\t\t\t,\t(this.memory.charCodeAt(p64+3) << 8) | this.memory.charCodeAt(p64+2)\n\t\t\t\t,\t(this.memory.charCodeAt(p64+5) << 8) | this.memory.charCodeAt(p64+4)\n\t\t\t\t,\t(this.memory.charCodeAt(p64+7) << 8) | this.memory.charCodeAt(p64+6)\n\t\t\t\t)\n\t\t\tthis.v4.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t} else {\n\t\t\tvar other\n\t\t\tother = UINT64(\n\t\t\t\t\t(this.memory[p64+1] << 8) | this.memory[p64]\n\t\t\t\t,\t(this.memory[p64+3] << 8) | this.memory[p64+2]\n\t\t\t\t,\t(this.memory[p64+5] << 8) | this.memory[p64+4]\n\t\t\t\t,\t(this.memory[p64+7] << 8) | this.memory[p64+6]\n\t\t\t\t)\n\t\t\tthis.v1.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t\tp64 += 8\n\t\t\tother = UINT64(\n\t\t\t\t\t(this.memory[p64+1] << 8) | this.memory[p64]\n\t\t\t\t,\t(this.memory[p64+3] << 8) | this.memory[p64+2]\n\t\t\t\t,\t(this.memory[p64+5] << 8) | this.memory[p64+4]\n\t\t\t\t,\t(this.memory[p64+7] << 8) | this.memory[p64+6]\n\t\t\t\t)\n\t\t\tthis.v2.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t\tp64 += 8\n\t\t\tother = UINT64(\n\t\t\t\t\t(this.memory[p64+1] << 8) | this.memory[p64]\n\t\t\t\t,\t(this.memory[p64+3] << 8) | this.memory[p64+2]\n\t\t\t\t,\t(this.memory[p64+5] << 8) | this.memory[p64+4]\n\t\t\t\t,\t(this.memory[p64+7] << 8) | this.memory[p64+6]\n\t\t\t\t)\n\t\t\tthis.v3.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t\tp64 += 8\n\t\t\tother = UINT64(\n\t\t\t\t\t(this.memory[p64+1] << 8) | this.memory[p64]\n\t\t\t\t,\t(this.memory[p64+3] << 8) | this.memory[p64+2]\n\t\t\t\t,\t(this.memory[p64+5] << 8) | this.memory[p64+4]\n\t\t\t\t,\t(this.memory[p64+7] << 8) | this.memory[p64+6]\n\t\t\t\t)\n\t\t\tthis.v4.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t}\n\n\t\tp += 32 - this.memsize\n\t\tthis.memsize = 0\n\t\tif (isString) this.memory = ''\n\t}\n\n\tif (p <= bEnd - 32)\n\t{\n\t\tvar limit = bEnd - 32\n\n\t\tdo\n\t\t{\n\t\t\tif (isString) {\n\t\t\t\tvar other\n\t\t\t\tother = UINT64(\n\t\t\t\t\t\t(input.charCodeAt(p+1) << 8) | input.charCodeAt(p)\n\t\t\t\t\t,\t(input.charCodeAt(p+3) << 8) | input.charCodeAt(p+2)\n\t\t\t\t\t,\t(input.charCodeAt(p+5) << 8) | input.charCodeAt(p+4)\n\t\t\t\t\t,\t(input.charCodeAt(p+7) << 8) | input.charCodeAt(p+6)\n\t\t\t\t\t)\n\t\t\t\tthis.v1.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t\t\tp += 8\n\t\t\t\tother = UINT64(\n\t\t\t\t\t\t(input.charCodeAt(p+1) << 8) | input.charCodeAt(p)\n\t\t\t\t\t,\t(input.charCodeAt(p+3) << 8) | input.charCodeAt(p+2)\n\t\t\t\t\t,\t(input.charCodeAt(p+5) << 8) | input.charCodeAt(p+4)\n\t\t\t\t\t,\t(input.charCodeAt(p+7) << 8) | input.charCodeAt(p+6)\n\t\t\t\t\t)\n\t\t\t\tthis.v2.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t\t\tp += 8\n\t\t\t\tother = UINT64(\n\t\t\t\t\t\t(input.charCodeAt(p+1) << 8) | input.charCodeAt(p)\n\t\t\t\t\t,\t(input.charCodeAt(p+3) << 8) | input.charCodeAt(p+2)\n\t\t\t\t\t,\t(input.charCodeAt(p+5) << 8) | input.charCodeAt(p+4)\n\t\t\t\t\t,\t(input.charCodeAt(p+7) << 8) | input.charCodeAt(p+6)\n\t\t\t\t\t)\n\t\t\t\tthis.v3.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t\t\tp += 8\n\t\t\t\tother = UINT64(\n\t\t\t\t\t\t(input.charCodeAt(p+1) << 8) | input.charCodeAt(p)\n\t\t\t\t\t,\t(input.charCodeAt(p+3) << 8) | input.charCodeAt(p+2)\n\t\t\t\t\t,\t(input.charCodeAt(p+5) << 8) | input.charCodeAt(p+4)\n\t\t\t\t\t,\t(input.charCodeAt(p+7) << 8) | input.charCodeAt(p+6)\n\t\t\t\t\t)\n\t\t\t\tthis.v4.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t\t} else {\n\t\t\t\tvar other\n\t\t\t\tother = UINT64(\n\t\t\t\t\t\t(input[p+1] << 8) | input[p]\n\t\t\t\t\t,\t(input[p+3] << 8) | input[p+2]\n\t\t\t\t\t,\t(input[p+5] << 8) | input[p+4]\n\t\t\t\t\t,\t(input[p+7] << 8) | input[p+6]\n\t\t\t\t\t)\n\t\t\t\tthis.v1.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t\t\tp += 8\n\t\t\t\tother = UINT64(\n\t\t\t\t\t\t(input[p+1] << 8) | input[p]\n\t\t\t\t\t,\t(input[p+3] << 8) | input[p+2]\n\t\t\t\t\t,\t(input[p+5] << 8) | input[p+4]\n\t\t\t\t\t,\t(input[p+7] << 8) | input[p+6]\n\t\t\t\t\t)\n\t\t\t\tthis.v2.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t\t\tp += 8\n\t\t\t\tother = UINT64(\n\t\t\t\t\t\t(input[p+1] << 8) | input[p]\n\t\t\t\t\t,\t(input[p+3] << 8) | input[p+2]\n\t\t\t\t\t,\t(input[p+5] << 8) | input[p+4]\n\t\t\t\t\t,\t(input[p+7] << 8) | input[p+6]\n\t\t\t\t\t)\n\t\t\t\tthis.v3.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t\t\tp += 8\n\t\t\t\tother = UINT64(\n\t\t\t\t\t\t(input[p+1] << 8) | input[p]\n\t\t\t\t\t,\t(input[p+3] << 8) | input[p+2]\n\t\t\t\t\t,\t(input[p+5] << 8) | input[p+4]\n\t\t\t\t\t,\t(input[p+7] << 8) | input[p+6]\n\t\t\t\t\t)\n\t\t\t\tthis.v4.add( other.multiply(PRIME64_2) ).rotl(31).multiply(PRIME64_1);\n\t\t\t}\n\t\t\tp += 8\n\t\t} while (p <= limit)\n\t}\n\n\tif (p < bEnd)\n\t{\n\t\t// XXH64_memcpy(this.memory, p, bEnd-p);\n\t\tif (isString) {\n\t\t\tthis.memory += input.slice(p)\n\t\t} else if (isArrayBuffer) {\n\t\t\tthis.memory.set( input.subarray(p, bEnd), this.memsize )\n\t\t} else {\n\t\t\tinput.copy( this.memory, this.memsize, p, bEnd )\n\t\t}\n\n\t\tthis.memsize = bEnd - p\n\t}\n\n\treturn this\n}\n\n/**\n * Finalize the XXH64 computation. The XXH64 instance is ready for reuse for the given seed\n * @method digest\n * @return {UINT64} xxHash\n */\nXXH64.prototype.digest = function () {\n\tvar input = this.memory\n\tvar isString = typeof input == 'string'\n\tvar p = 0\n\tvar bEnd = this.memsize\n\tvar h64, h\n\tvar u = new UINT64\n\n\tif (this.total_len >= 32)\n\t{\n\t\th64 = this.v1.clone().rotl(1)\n\t\th64.add( this.v2.clone().rotl(7) )\n\t\th64.add( this.v3.clone().rotl(12) )\n\t\th64.add( this.v4.clone().rotl(18) )\n\n\t\th64.xor( this.v1.multiply(PRIME64_2).rotl(31).multiply(PRIME64_1) )\n\t\th64.multiply(PRIME64_1).add(PRIME64_4)\n\n\t\th64.xor( this.v2.multiply(PRIME64_2).rotl(31).multiply(PRIME64_1) )\n\t\th64.multiply(PRIME64_1).add(PRIME64_4)\n\n\t\th64.xor( this.v3.multiply(PRIME64_2).rotl(31).multiply(PRIME64_1) )\n\t\th64.multiply(PRIME64_1).add(PRIME64_4)\n\n\t\th64.xor( this.v4.multiply(PRIME64_2).rotl(31).multiply(PRIME64_1) )\n\t\th64.multiply(PRIME64_1).add(PRIME64_4)\n\t}\n\telse\n\t{\n\t\th64 = this.seed.clone().add( PRIME64_5 )\n\t}\n\n\th64.add( u.fromNumber(this.total_len) )\n\n\twhile (p <= bEnd - 8)\n\t{\n\t\tif (isString) {\n\t\t\tu.fromBits(\n\t\t\t\t(input.charCodeAt(p+1) << 8) | input.charCodeAt(p)\n\t\t\t,\t(input.charCodeAt(p+3) << 8) | input.charCodeAt(p+2)\n\t\t\t,\t(input.charCodeAt(p+5) << 8) | input.charCodeAt(p+4)\n\t\t\t,\t(input.charCodeAt(p+7) << 8) | input.charCodeAt(p+6)\n\t\t\t)\n\t\t} else {\n\t\t\tu.fromBits(\n\t\t\t\t(input[p+1] << 8) | input[p]\n\t\t\t,\t(input[p+3] << 8) | input[p+2]\n\t\t\t,\t(input[p+5] << 8) | input[p+4]\n\t\t\t,\t(input[p+7] << 8) | input[p+6]\n\t\t\t)\n\t\t}\n\t\tu.multiply(PRIME64_2).rotl(31).multiply(PRIME64_1)\n\t\th64\n\t\t\t.xor(u)\n\t\t\t.rotl(27)\n\t\t\t.multiply( PRIME64_1 )\n\t\t\t.add( PRIME64_4 )\n\t\tp += 8\n\t}\n\n\tif (p + 4 <= bEnd) {\n\t\tif (isString) {\n\t\t\tu.fromBits(\n\t\t\t\t(input.charCodeAt(p+1) << 8) | input.charCodeAt(p)\n\t\t\t,\t(input.charCodeAt(p+3) << 8) | input.charCodeAt(p+2)\n\t\t\t,\t0\n\t\t\t,\t0\n\t\t\t)\n\t\t} else {\n\t\t\tu.fromBits(\n\t\t\t\t(input[p+1] << 8) | input[p]\n\t\t\t,\t(input[p+3] << 8) | input[p+2]\n\t\t\t,\t0\n\t\t\t,\t0\n\t\t\t)\n\t\t}\n\t\th64\n\t\t\t.xor( u.multiply(PRIME64_1) )\n\t\t\t.rotl(23)\n\t\t\t.multiply( PRIME64_2 )\n\t\t\t.add( PRIME64_3 )\n\t\tp += 4\n\t}\n\n\twhile (p < bEnd)\n\t{\n\t\tu.fromBits( isString ? input.charCodeAt(p++) : input[p++], 0, 0, 0 )\n\t\th64\n\t\t\t.xor( u.multiply(PRIME64_5) )\n\t\t\t.rotl(11)\n\t\t\t.multiply(PRIME64_1)\n\t}\n\n\th = h64.clone().shiftRight(33)\n\th64.xor(h).multiply(PRIME64_2)\n\n\th = h64.clone().shiftRight(29)\n\th64.xor(h).multiply(PRIME64_3)\n\n\th = h64.clone().shiftRight(32)\n\th64.xor(h)\n\n\t// Reset the state\n\tthis.init( this.seed )\n\n\treturn h64\n}\n\nmodule.exports = XXH64\n","module.exports = {\n\th32: require(\"./xxhash\")\n,\th64: require(\"./xxhash64\")\n}\n","//import { x64 } from 'murmurhash3js';\nimport xxhash from 'xxhashjs';\n//\n// TYPES\n//\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\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 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 { PoolClient } from 'pg';\nimport { IResource } from '../../fhir-utils/commonTypes.js'\nimport { PGPoolManager } from './pgpoolmanager.js'\nimport { defaultLogger } from '@nsshunt/stsutils';\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 {\n #poolManager: PGPoolManager;\n\n constructor(poolManager: PGPoolManager) {\n this.#poolManager = poolManager;\n }\n\n async InsertResourceEx(client: PoolClient, data: NamedResourceInsert): Promise<void> {\n try {\n 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 `,\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 } catch (error) {\n defaultLogger.error(`DBSTSResource:InsertResource(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async InsertResource(data: NamedResourceInsert): Promise<void> {\n try {\n const client = await this.#poolManager.connectReadWrite();\n try {\n await this.InsertResourceEx(client, data);\n } catch (error) {\n defaultLogger.error(`DBSTSResource:InsertResource(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:InsertResource(): Connection Error: [${error}]`)\n }\n }\n\n async UpdateResourceRecordEx(client: PoolClient, data: NamedResourceUpdate): Promise<boolean | 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 `,\n [BigInt(data.RES_UPDATED), data.RES_ID, data.RES_TYPE, data.RES_VER]\n );\n return (res.rowCount ? res.rowCount > 0 : false);\n } catch (error) {\n defaultLogger.error(`DBSTSResource:UpdateResourceRecordEx(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async UpdateResourceRecord(data: NamedResourceUpdate): Promise<boolean | undefined> {\n try {\n const client = await this.#poolManager.connectReadWrite();\n try {\n return await this.UpdateResourceRecordEx(client, data);\n } catch (error) {\n defaultLogger.error(`DBSTSResource:UpdateResourceRecord-1(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:UpdateResourceRecord-2(): Connection Error: [${error}]`)\n }\n }\n\n async DeleteResourceRecordEx(client: PoolClient, data: NamedResourceDelete): Promise<boolean | 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 `,\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.rowCount ? res.rowCount > 0 : false);\n } catch (error) {\n defaultLogger.error(`DBSTSResource:DeleteResourceRecord(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async DeleteResourceRecord(data: NamedResourceDelete): Promise<boolean | undefined> {\n try {\n const client = await this.#poolManager.connectReadWrite();\n try {\n return await this.DeleteResourceRecordEx(client, data);\n } catch (error) {\n defaultLogger.error(`DBSTSResource:DeleteResourceRecord(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:DeleteResourceRecord(): Connection Error: [${error}]`)\n }\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 defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n throw (error);\n }\n }\n\n async ReadResourceRecord(PID: string): Promise<IResource | undefined> {\n try {\n const client = await this.#poolManager.connectReadOnly();\n try {\n return await this.ReadResourceRecordEx(client, PID);\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadResourceRecord(): Connection Error: [${error}]`)\n }\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 defaultLogger.error(`DBSTSResource:ReadAllResourceRecords(): Query Error: [${error}]`)\n throw error;\n }\n }\n \n async ReadAllResourceRecords(): Promise<IResource[] | undefined> {\n try {\n const client = await this.#poolManager.connectReadOnly();\n try {\n return await this.ReadAllResourceRecordsEx(client);\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadAllResourceRecords(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResource:ReadAllResourceRecords(): Connection Error: [${error}]`)\n }\n }\n}\n","import { PGPoolManager } from './pgpoolmanager.js'\nimport { IResourceVersion } from '../../fhir-utils/commonTypes.js'\nimport { defaultLogger } from '@nsshunt/stsutils';\nimport { PoolClient } from 'pg';\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 {\n #poolManager: PGPoolManager;\n\n constructor(poolManager: PGPoolManager) {\n this.#poolManager = poolManager;\n }\n\n async InsertResourceVersionEx(client: PoolClient, data: NamedResourceVersionInsert): Promise<void> {\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\n 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 `,values);\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): Query Error: [${error}]`)\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values PID: [${values[0]}]`)\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values PARTITION_ID: [${values[1]}]`)\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values PARTITION_DATE: [${values[2]}]`)\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values RES_ID: [${values[3]}]`)\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values RES_TYPE: [${values[4]}]`)\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values RES_VER: [${values[5]}]`)\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): --> Values OPERATION: [${values[6]}]`)\n throw error;\n }\n }\n\n async InsertResourceVersion(data: NamedResourceVersionInsert): Promise<void> {\n try {\n const client = await this.#poolManager.connectReadWrite();\n try {\n await this.InsertResourceVersionEx(client, data);\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:InsertResourceVersion(): Connection Error: [${error}]`)\n }\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 defaultLogger.error(`DBSTSResourceVersion:ReadResourceVersionRecord(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async ReadResourceVersionRecord(PID: string, RES_VER: number): Promise<IResourceVersion | undefined> {\n try {\n const client = await this.#poolManager.connectReadWrite();\n try {\n return await this.ReadResourceVersionRecordEx(client, PID, RES_VER);\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:ReadResourceVersionRecord(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:ReadResourceVersionRecord(): Connection Error: [${error}]`)\n }\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 defaultLogger.error(`DBSTSResourceVersion:ReadAllResourceVersionRecords(): Query Error: [${error}]`)\n throw error;\n }\n }\n\n async ReadAllResourceVersionRecords(): Promise<IResourceVersion[] | undefined> {\n try {\n const client = await this.#poolManager.connectReadWrite();\n try {\n return await this.ReadAllResourceVersionRecordsEx(client);\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:ReadAllResourceVersionRecords(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:ReadAllResourceVersionRecords(): Connection Error: [${error}]`)\n }\n }\n\n /*\n async UpdateResourceVersionRecord(data: NamedResourceVersionUpdate): Promise<boolean | undefined> {\n try {\n const client = await this.#poolManager.connectReadWrite();\n try {\n const res = await client.query(\n `\n UPDATE stsresfhirver\n SET RES_VER = RES_VER + 1,\n RES = $1\n WHERE RES_ID = $2 AND RES_VER = $3\n `,\n [data.RES, data.RES_ID, data.RES_VER]\n );\n return (res.rowCount ? res.rowCount > 0 : false);\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:UpdateResourceVersionRecord(): Query Error: [${error}]`)\n } finally {\n client.release();\n }\n } catch (error) {\n defaultLogger.error(`DBSTSResourceVersion:UpdateResourceVersionRecord(): Connection Error: [${error}]`)\n }\n }\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 } 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(this.#poolManager);\n this.#dbSTSResourceVersion = new DBSTSResourceVersion(this.#poolManager);\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 /*\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 try {\n let PK = randomUUID();\n const RES_ID = resource.id!;\n const RES_TYPE = resource.resourceType;\n const RES = JSON.stringify(resource);\n const now = new Date().getTime();\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.connectReadWrite();\n useTransaction = true;\n }\n try {\n if (useTransaction) {\n await client.query('BEGIN');\n }\n\n const resourceRunResult = await this.#dbSTSResource.InsertResourceEx(client, {\n PID: PK,\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\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: 1,\n OPERATION: 'POST',\n RES\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 } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`PGFhirAccessLayer:CreateResource(): [${error}]`);\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 try {\n const RES_ID = resource.id!;\n const RES_TYPE = resource.resourceType;\n const RES = JSON.stringify(resource);\n const now = new Date().getTime();\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.connectReadWrite();\n useTransaction = true;\n }\n try {\n if (useTransaction) {\n await client.query('BEGIN');\n }\n\n const resourceRunResult = await this.#dbSTSResource.UpdateResourceRecordEx(client, {\n RES_TYPE,\n RES_ID,\n RES_VER,\n RES_UPDATED: now\n });\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: (RES_VER + 1),\n OPERATION: operation,\n RES\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 } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`PGFhirAccessLayer:UpdateResource(): [${error}]`);\n }\n }\n }\n\n DeleteResource = async (resource: Resource, RES_VER: number, transactionHandle?: string): Promise<Resource | undefined> => {\n if (this.#poolManager) {\n try {\n const RES_ID = resource.id!;\n const RES_TYPE = resource.resourceType;\n\n const now = new Date(DateTime.fromISO(resource.meta!.lastUpdated as string).toJSDate()).getTime();\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.connectReadWrite();\n useTransaction = true;\n }\n try {\n if (useTransaction) {\n await client.query('BEGIN');\n }\n\n const resourceRunResult = 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\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: (RES_VER + 1),\n OPERATION: 'DELETE',\n RES: ''\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 } finally {\n if (useTransaction) {\n client.release();\n }\n }\n } catch (error) {\n defaultLogger.error(`PGFhirAccessLayer:DeleteResource(): [${error}]`);\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 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\n ReadResourceRecordWithVersion = async (RES_TYPE: string, RES_ID: string, RES_VER: number, transactionHandle?: string): Promise<IResource | undefined> => {\n if (this.#poolManager) {\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\n ReadResourceInstanceWithAllVersions = async (RES_TYPE: string, RES_ID: string, transactionHandle?: string): Promise<IResource[] | undefined> => {\n if (this.#poolManager) {\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\n ReadResourcesWithAllVersions = async (RES_TYPE: string, transactionHandle?: string): Promise<IResource[] | undefined> => {\n if (this.#poolManager) {\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\n ReadAllResourcesWithVersions = async (transactionHandle?: string) => {\n if (this.#poolManager) {\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\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 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\n ExecuteReadQuery = async (queryData: any, transactionHandle?: string): Promise<any> => {\n if (this.#poolManager) {\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\n TruncateAll = async () => {\n if (this.#poolManager) {\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}\n"],"x_google_ignoreList":[1,2,3,4,5,6],"mappings":"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"}