@synanetics/syn-utils
v3.0.0
Published
synanetics util functionality
Downloads
141
Maintainers
Keywords
Readme
@synanetics/syn-utils
A collection of common utility functions used across multiple Synanetics repositories
Usage
const {
getPrefix, removePrefix
} = require('@synanetics/syn-utils');
// or
import {
getPrefix, removePrefix
} from '@synanetics/syn-utils';
API
Paging
Function: pageBuilder
The pageBuilder function takes in an array of sorted sourceBundles and pageConfig, and returns a bundle page with those with the combined resources from all the bundles.
Arguments
function pageBuilder(sourceBundles: SourceBundle[], config: PageConfig) => PageOutput
interface SourceBundle {
sourceId: string;
bundle: Bundle;
}
interface SortConfig {
fhirSorter: FhirSorter;
sortTerms: string[];
allowChainedSort?: boolean;
}
interface PageConfig {
pagingBaseUrl: URL;
pageSize?: number;
sortConfig?: SortConfig;
currentPageNum?: number;
partialPage?: Bundle;
}
interface PageOutput {
completePage: boolean;
page: Bundle;
sourceBundles: SourceBundle[];
bundleToReplace?: string;
}
- sourceBundles
- The Bundles to combine into a single page
- All Bundles must have a 'Total'
- At least one Bundle must have entries
- config
- The config defines how the page is to be built
- pagingBaseUrl
- The url to which the paging links can be appended
- e.g https://fhir.store.nhs.uk/patient?_queryId=uuid ->
- {relation: 'self', url: 'https://fhir.store.nhs.uk/patient?_queryId=uuid&_page=4'}
- {relation: 'first', url: 'https://fhir.store.nhs.uk/patient?_queryId=uuid&_page=1'}
- {relation: 'last', url: 'https://fhir.store.nhs.uk/patient?_queryId=uuid&_page=9'}
- {relation: 'previous', url: 'https://fhir.store.nhs.uk/patient?_queryId=uuid&_page=3'}
- {relation: 'next', url: 'https://fhir.store.nhs.uk/patient?_queryId=uuid&_page=5'}
- pageSize
- The desired maximum page size
- Must be a positive integer
- Will default to 100 if not provided
- sortConfig?
- This is an optional parameter, if it is not provided the pageBuilder will iterate over each source to build the page
- fhirSorter
- An instance of the FhirSorter from the @synanetics/fhir-sort package
- sortTerms
- An array of strings that will be used to sort the resources in the Bundles
- e.g ['family', '_lastUpdated']
- allowChainedSort
- A boolean to allow/disallow chained sorting
- For details on chained sorting see the @synanetics/fhir-sort package README
- This parameter is optional and will default to false if not provided
- currentPageNum?
- The number of the page being built
- e.g If you are calling the pageBuilder to build the 3rd page in a set of 5, this value should be 3
- This value will default to 1 if not provided
- partialPage?
- This is an optional parameter
- This parameter should only be provided when the pageBuilder previously returned an incomplete page
- This happens when the pageBuilder has emptied an input bundle and requires a replacement
- When you recall pageBuilder with the new bundle, you will pass in the incomplete page in partialPage returned by the first call
Return Values
- completePage
- This is a boolean
- This is true when:
- The pageBuilder was able to build a page of the desired maximum size
- The page builder has emptied all the bundles and built the final page
- This is false when:
- The page builder emptied one of the input bundles before completing the page and has determined it needs a replacement
- page
- This is a FHIR Bundle
- Its total will be the combined total of all bundles
- It will have paging links
- Its entries will be populated from the input bundles
- Outcomes come first
- Any outcomes from all input bundles will appear first on the page
- These can be in any order
- Matches come second
- A sorted, if sortTerms are provided, subset of the matches from all the input bundles will come after the outcomes
- This will most often not contain all the matches from all the inputs, as the page size will likely be smaller than the number of matches provided
- Includes come third
- Any includes referenced in the matches will come after the matches
- Each include will be referenced at least once by at least one match
- Each include will only appear once
- Outcomes come first
- sourceBundles
- The sourceBundles outputted by the page builder are similar to the ones inputted
- The key difference is the output bundles will not contain any matches or outcomes already put into a page
- e.g If we have input bundles with 5 matches each for 5 sources, and a page size of 10, the output bundles may contain 3 matches each for 5 sources.
- Bundles that are emptied of matches will not be returned by the pageBuilder
- bundleToReplace?
- If the pageBuilder empties a paginated Bundle that is not on its last page, it needs to request a new bundle
- When this occurs it populates this optional string with the source id of the bundle to be replaced
Usage
This is an example flow where the first call returns a complete page, and the second call requires a replacement bundle.
First Call:
- FHIR query received requiring pagination
- Gather the sorted Bundles from each source
- Call the pageBuilder with the source Bundles, and desired config for page 1
- pageBuilder returns completed page, and partially consumed input bundles
- Cache the page, and partially consumed input bundles
- Return the page
Second Call (with emptied Bundle):
- Second page requested
- Retrieve partially consumed input bundles from cache
- Call the pageBuilder with the partially consumed Bundles, and desired config for page 2
- pageBuilder responds with an incomplete page, partially consumed Bundles, and requests a replacement Bundle from "source1"
- Retrieve the next Bundle from "source1"
- Call the pageBuilder with the partially consumed Bundles, the fresh Bundle from "source1", desired config for page 2 and the incomplete page previously returned
- pageBuilder returns completed page, and partially consumed input bundles
- Cache the page, and partially consumed input bundles
- Return the page
Prefix
Defaults
The prefix functions have default configuration values/functions which are as below.
const defaultPrefixDelimiter: string = '.';
const defaultEscapeRegex = (string: string): string => string.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
const defaultPrefixRegex: string = `^(?:.*/)?(?<prefix>.*?)${defaultEsc
apeRegex(defaultPrefixDelimiter)}.*`;
Function: getPrefix
The get prefix function takes in a string and returns a prefix that matches the provided arguments.
Arguments
function getPrefix(value: string, validPrefixes?: string[], prefixRegex: string = defaultPrefixRegex) => string
- value
- The string to retrieve the prefix from
- If no value is provided an error will be thrown
- validPrefixes
- An array of valid prefix strings
- If this is not provided, all prefixes are considered valid
- dpPrefixRegex
- Defaults to defaultDpPrefixRegex
- This regex is used to find the prefix in value
Usage
//Expect value: wow
getPrefix('wow.theRest');
//Expect value: apple
getPrefix('apple.pie', ['apple', 'pear']);
// Expect error: No value provided
getPrefix();
//Expect Error: No valid prefixes found
getPrefix('this has no prefix');
//Expect Error: No valid prefixes found
getPrefix('tomato.pie', ['apple', 'pear']);
Function: removePrefix
The get prefix function takes in a string and returns a prefix that matches the provided arguments.
Arguments
function removePrefix(value: string, prefix: string, prefixDelimiter: string = defaultPrefixDelimiter, escapeRegex: (string: string) => string = defaultEscapeRegex) => string
- value
- The string to remove the prefix from
- If no value is provided an error will be thrown
- prefix
- The prefix to remove
- If no prefix is provided an error will be thrown
- prefixDelimiter
- Defaults to defaultPrefixDelimiter
- This string is used to split prefix from value
- escapeRegex
- Defaults to defaultEscapeRegex
- This regex is applied to the prefixDelimiter to escape protected characters
Usage
//Expect value: theRest
removePrefix('wow.theRest', 'wow');
//Expect value: apple.pie
removePrefix('apple.pie', 'pear');
// Expect error: No value provided
removePrefix();
// Expect error: No prefix provided
removePrefix('wow');
Function: removePrefixFromFhirObj
The removePrefixFromFhirObj function removes a prefix string from all ids and reference ids in a FHIR object
function removePrefixFromFhirObj<T extends (fhir3.FhirResource | fhir4.FhirResource)>(
input: T,
prefix: string,
prefixDelimiter?: string,
maxDepth?: number,
) => T
Arguments
- input is a FHIR stu3/r4 resource as defined in the @types/fhir package such as a Patient resource
- prefix is a string such as 'HUB' that should be removed from all ids and reference ids
- prefixDelimiter is a string that is used to delimit where a prefix ends and an id begins, this defaults to '.'
- maxDepth is a number that represents the maximum recursion depth that is allowed before an error is thrown, this defaults to 15
Usage
//Input resource:
const patient: Patient = {
id: 'HUB.pat1',
resourceType: 'Patient',
generalPractitioner: [
{
reference: '#contained',
},
{
reference: 'Organization/HUB.org1',
},
{
reference: 'Organization/HUB.org1',
},
{
reference: 'Practitioner/HUB.DDCR.pra1',
},
{
reference: 'Practitioner/HUB.pra2/_history/4',
},
],
managingOrganization: {
reference: 'url/fhir/Organization/HUB.DDCR.org2',
},
};
const unprefixedPatient: Patient = removePrefixFromFhirObj(patient, 'HUB');
// expect unprefixedPatient to equal expectedPatient
const expectedPatient: Patient = {
id: 'pat1',
resourceType: 'Patient',
generalPractitioner: [
{
reference: '#contained',
},
{
reference: 'Organization/org1',
},
{
reference: 'Organization/org1',
},
{
reference: 'Practitioner/DDCR.pra1',
},
{
reference: 'Practitioner/pra2/_history/4',
},
],
managingOrganization: {
reference: 'url/fhir/Organization/DDCR.org2',
},
};
Reference
Interface: ReferenceDetails
interface ReferenceDetails {
original: string;
contained: boolean;
version: number;
id?: string;
type?: string;
criteria?: string;
url?: string;
relative?: string;
}
Function: getReferenceDetails
The get getReferenceDetails function takes in a reference string and extracts the details into a ReferenceDetails object
Arguments
function getReferenceDetails(referenceString: string) => ReferenceDetails
- referenceString
- The string to extract the details from
- If no referenceString is provided an error will be thrown
Usage
//Expect value:
const expectedValue = {
original: '#p1',
contained: true,
version: 1,
id: 'p1'
}
getReferenceDetails('#p1');
//Expect value:
const expectedValue = {
original: 'ValueSet?url=http://hl7.org/fhir/ValueSet/my-valueset&version=0.8',
contained: false,
version: 1,
type: 'ValueSet',
criteria: 'url=http://hl7.org/fhir/ValueSet/my-valueset&version=0.8',
}
getReferenceDetails('ValueSet?url=http://hl7.org/fhir/ValueSet/my-valueset&version=0.8');
//Expect value:
const expectedValue = {
original: 'url/fhir/r4/Patient/12345',
contained: false,
version: 1,
type: 'Patient',
id: '12345',
url: 'url/fhir/r4/Patient/12345',
relative: 'Patient/12345',
}
getReferenceDetails('url/fhir/r4/Patient/12345');
//Expect value:
const expectedValue = {
original: 'Patient/12345/_history/5',
contained: false,
version: 5,
type: 'Patient',
id: '12345',
relative: 'Patient/12345',
}
getReferenceDetails('Patient/12345/_history/5');
Function: getUniqueRelativeReferences
The get getUniqueRelativeReferences function takes in a fhir resource and extracts unique relative reference strings
function getUniqueRelativeReferences(
input: Record<any, any>,
relativeRefs?: Set<string>,
maxDepth?: string,
) => Set<string>
Arguments
- input is a FHIR resource as defined in the @types/fhir package such as a Patient resource
- relativeRefs is a set of unique relative reference strings, e.g Patient/12345, this defaults to an empty set
- maxDepth is a number that represents the maximum recursion depth that is allowed before an error is thrown, this defaults to 15
Usage
//Input resource:
const patient: Patient = {
resourceType: 'Patient',
generalPractitioner: [
{
reference: '#notRelative',
},
{
reference: 'Organization/1',
},
{
reference: 'Organization/1',
},
{
reference: 'Practitioner/1',
},
{
reference: 'Practitioner/2/_history/4',
},
],
managingOrganization: {
reference: 'url/fhir/Organization/2',
},
};
//Expect set to contain 'Organization/1', 'Practitioner/1', 'Practitioner/2', 'Organization/2'
getUniqueRelativeReferences(patient);
Rebase References
Function: rebaseReferences
A function to prefix any identifiers or relative references with the supplied string.
Usage:
const resource = {
id: 'DEF.123',
subject: {
reference: 'Patient/DEF.456',
},
};
const rebasedResource = rebaseReferences(resource, 'ABC');
expect(resource).toEqual({
id: 'ABC.DEF.123',
subject: {
reference: 'Patient/ABC.DEF.456',
},
})