3.0.2 • Published 7 months ago

@synanetics/syn-utils v3.0.2

Weekly downloads
-
License
MIT
Repository
bitbucket
Last release
7 months ago

@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

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
  • 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:

  1. FHIR query received requiring pagination
  2. Gather the sorted Bundles from each source
  3. Call the pageBuilder with the source Bundles, and desired config for page 1
  4. pageBuilder returns completed page, and partially consumed input bundles
  5. Cache the page, and partially consumed input bundles
  6. Return the page

Second Call (with emptied Bundle):

  1. Second page requested
  2. Retrieve partially consumed input bundles from cache
  3. Call the pageBuilder with the partially consumed Bundles, and desired config for page 2
  4. pageBuilder responds with an incomplete page, partially consumed Bundles, and requests a replacement Bundle from "source1"
  5. Retrieve the next Bundle from "source1"
  6. Call the pageBuilder with the partially consumed Bundles, the fresh Bundle from "source1", desired config for page 2 and the incomplete page previously returned
  7. pageBuilder returns completed page, and partially consumed input bundles
  8. Cache the page, and partially consumed input bundles
  9. 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',
    },
})
3.0.2

7 months ago

3.0.1

7 months ago

3.0.0

11 months ago

2.0.2

11 months ago

2.0.1

11 months ago

2.0.0

11 months ago

1.3.0

1 year ago

1.2.0

1 year ago

1.1.0

1 year ago

1.0.0

1 year ago