@medplum/core 2.0.23 → 2.0.24

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.
Files changed (55) hide show
  1. package/dist/cjs/index.cjs +14080 -13352
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs/index.min.cjs +1 -1
  4. package/dist/esm/access.mjs +142 -0
  5. package/dist/esm/access.mjs.map +1 -0
  6. package/dist/esm/bundle.mjs +3 -3
  7. package/dist/esm/bundle.mjs.map +1 -1
  8. package/dist/esm/client.mjs +49 -25
  9. package/dist/esm/client.mjs.map +1 -1
  10. package/dist/esm/fhirlexer/parse.mjs.map +1 -1
  11. package/dist/esm/fhirmapper/parse.mjs +1 -1
  12. package/dist/esm/fhirmapper/parse.mjs.map +1 -1
  13. package/dist/esm/fhirpath/functions.mjs +2 -2
  14. package/dist/esm/fhirpath/functions.mjs.map +1 -1
  15. package/dist/esm/fhirpath/parse.mjs +2 -1
  16. package/dist/esm/fhirpath/parse.mjs.map +1 -1
  17. package/dist/esm/fhirpath/utils.mjs +4 -5
  18. package/dist/esm/fhirpath/utils.mjs.map +1 -1
  19. package/dist/esm/format.mjs +1 -1
  20. package/dist/esm/format.mjs.map +1 -1
  21. package/dist/esm/hl7.mjs +6 -6
  22. package/dist/esm/hl7.mjs.map +1 -1
  23. package/dist/esm/index.min.mjs +1 -1
  24. package/dist/esm/index.mjs +5 -2
  25. package/dist/esm/index.mjs.map +1 -1
  26. package/dist/esm/outcomes.mjs +38 -14
  27. package/dist/esm/outcomes.mjs.map +1 -1
  28. package/dist/esm/readablepromise.mjs +1 -1
  29. package/dist/esm/readablepromise.mjs.map +1 -1
  30. package/dist/esm/schema.mjs +1 -1
  31. package/dist/esm/schema.mjs.map +1 -1
  32. package/dist/esm/search/details.mjs +14 -16
  33. package/dist/esm/search/details.mjs.map +1 -1
  34. package/dist/esm/search/match.mjs +7 -5
  35. package/dist/esm/search/match.mjs.map +1 -1
  36. package/dist/esm/search/search.mjs +14 -5
  37. package/dist/esm/search/search.mjs.map +1 -1
  38. package/dist/esm/types.mjs +1 -1
  39. package/dist/esm/types.mjs.map +1 -1
  40. package/dist/esm/typeschema/types.mjs +278 -0
  41. package/dist/esm/typeschema/types.mjs.map +1 -0
  42. package/dist/esm/typeschema/validation.mjs +262 -0
  43. package/dist/esm/typeschema/validation.mjs.map +1 -0
  44. package/dist/esm/utils.mjs +3 -3
  45. package/dist/esm/utils.mjs.map +1 -1
  46. package/dist/types/access.d.ts +48 -0
  47. package/dist/types/client.d.ts +15 -20
  48. package/dist/types/fhirlexer/parse.d.ts +5 -4
  49. package/dist/types/fhirpath/functions.d.ts +1 -3
  50. package/dist/types/index.d.ts +3 -0
  51. package/dist/types/outcomes.d.ts +3 -1
  52. package/dist/types/search/search.d.ts +7 -0
  53. package/dist/types/typeschema/types.d.ts +5 -2
  54. package/dist/types/typeschema/validation.d.ts +2 -0
  55. package/package.json +1 -1
@@ -61,7 +61,7 @@ function toJsBoolean(obj) {
61
61
  * @returns The value of the property and the property type.
62
62
  */
63
63
  function getTypedPropertyValue(input, path) {
64
- if (!input?.value) {
64
+ if (!input.value) {
65
65
  return undefined;
66
66
  }
67
67
  const elementDefinition = getElementDefinition(input.type, path);
@@ -144,6 +144,7 @@ function getTypedPropertyValueWithoutSchema(typedValue, path) {
144
144
  // value + valueDecimal = ok, because "decimal" is valid
145
145
  // id + identifier = not ok, because "entifier" is not a valid type
146
146
  // resource + resourceType = not ok, because "type" is not a valid type
147
+ //eslint-disable-next-line guard-for-in
147
148
  for (const propertyType in PropertyType) {
148
149
  const propertyName = path + capitalize(propertyType);
149
150
  if (propertyName in input) {
@@ -362,10 +363,8 @@ function deepEquals(object1, object2) {
362
363
  return false;
363
364
  }
364
365
  }
365
- else {
366
- if (val1 !== val2) {
367
- return false;
368
- }
366
+ else if (val1 !== val2) {
367
+ return false;
369
368
  }
370
369
  }
371
370
  return true;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","sources":["../../../src/fhirpath/utils.ts"],"sourcesContent":["import { ElementDefinition, Period, Quantity } from '@medplum/fhirtypes';\nimport { buildTypeName, getElementDefinition, isResource, PropertyType, TypedValue } from '../types';\nimport { capitalize, isEmpty } from '../utils';\n\n/**\n * Returns a single element array with a typed boolean value.\n * @param value The primitive boolean value.\n * @returns Single element array with a typed boolean value.\n */\nexport function booleanToTypedValue(value: boolean): [TypedValue] {\n return [{ type: PropertyType.boolean, value }];\n}\n\n/**\n * Returns a \"best guess\" TypedValue for a given value.\n * @param value The unknown value to check.\n * @returns A \"best guess\" TypedValue for the given value.\n */\nexport function toTypedValue(value: unknown): TypedValue {\n if (value === null || value === undefined) {\n return { type: 'undefined', value: undefined };\n } else if (Number.isSafeInteger(value)) {\n return { type: PropertyType.integer, value };\n } else if (typeof value === 'number') {\n return { type: PropertyType.decimal, value };\n } else if (typeof value === 'boolean') {\n return { type: PropertyType.boolean, value };\n } else if (typeof value === 'string') {\n return { type: PropertyType.string, value };\n } else if (isQuantity(value)) {\n return { type: PropertyType.Quantity, value };\n } else if (isResource(value)) {\n return { type: value.resourceType, value };\n } else {\n return { type: PropertyType.BackboneElement, value };\n }\n}\n\n/**\n * Converts unknown object into a JavaScript boolean.\n * Note that this is different than the FHIRPath \"toBoolean\",\n * which has particular semantics around arrays, empty arrays, and type conversions.\n * @param obj Any value or array of values.\n * @returns The converted boolean value according to FHIRPath rules.\n */\nexport function toJsBoolean(obj: TypedValue[]): boolean {\n return obj.length === 0 ? false : !!obj[0].value;\n}\n\n/**\n * Returns the value of the property and the property type.\n * Some property definitions support multiple types.\n * For example, \"Observation.value[x]\" can be \"valueString\", \"valueInteger\", \"valueQuantity\", etc.\n * According to the spec, there can only be one property for a given element definition.\n * This function returns the value and the type.\n * @param input The base context (FHIR resource or backbone element).\n * @param path The property path.\n * @returns The value of the property and the property type.\n */\nexport function getTypedPropertyValue(input: TypedValue, path: string): TypedValue[] | TypedValue | undefined {\n if (!input?.value) {\n return undefined;\n }\n\n const elementDefinition = getElementDefinition(input.type, path);\n if (elementDefinition) {\n const typedResult = getTypedPropertyValueWithSchema(input, path, elementDefinition);\n if (typedResult) {\n return typedResult;\n }\n }\n\n return getTypedPropertyValueWithoutSchema(input, path);\n}\n\n/**\n * Returns the value of the property and the property type using a type schema.\n * @param input The base context (FHIR resource or backbone element).\n * @param path The property path.\n * @param property The property element definition.\n * @returns The value of the property and the property type.\n */\nfunction getTypedPropertyValueWithSchema(\n input: TypedValue,\n path: string,\n property: ElementDefinition\n): TypedValue[] | TypedValue | undefined {\n const types = property.type;\n if (!types || types.length === 0) {\n return undefined;\n }\n\n let resultValue: any = undefined;\n let resultType = 'undefined';\n\n if (types.length === 1) {\n resultValue = input.value[path];\n resultType = types[0].code as string;\n } else {\n for (const type of types) {\n const path2 = path.replace('[x]', '') + capitalize(type.code as string);\n if (path2 in input.value) {\n resultValue = input.value[path2];\n resultType = type.code as string;\n break;\n }\n }\n }\n\n if (isEmpty(resultValue)) {\n return undefined;\n }\n\n if (resultType === 'Element' || resultType === 'BackboneElement') {\n resultType = buildTypeName(property.path?.split('.') as string[]);\n }\n\n if (Array.isArray(resultValue)) {\n return resultValue.map((element) => toTypedValueWithType(element, resultType));\n } else {\n return toTypedValueWithType(resultValue, resultType);\n }\n}\n\nfunction toTypedValueWithType(value: any, type: string): TypedValue {\n if (type === 'Resource' && isResource(value)) {\n type = value.resourceType;\n }\n return { type, value };\n}\n\n/**\n * Returns the value of the property and the property type using a type schema.\n * Note that because the type schema is not available, this function may be inaccurate.\n * In some cases, that is the desired behavior.\n * @param typedValue The base context (FHIR resource or backbone element).\n * @param path The property path.\n * @returns The value of the property and the property type.\n */\nfunction getTypedPropertyValueWithoutSchema(\n typedValue: TypedValue,\n path: string\n): TypedValue[] | TypedValue | undefined {\n const input = typedValue.value;\n if (!input || typeof input !== 'object') {\n return undefined;\n }\n\n let result: any = undefined;\n if (path in input) {\n result = (input as { [key: string]: unknown })[path];\n } else {\n // Only support property names that would be valid types\n // Examples:\n // value + valueString = ok, because \"string\" is valid\n // value + valueDecimal = ok, because \"decimal\" is valid\n // id + identifier = not ok, because \"entifier\" is not a valid type\n // resource + resourceType = not ok, because \"type\" is not a valid type\n for (const propertyType in PropertyType) {\n const propertyName = path + capitalize(propertyType);\n if (propertyName in input) {\n result = (input as { [key: string]: unknown })[propertyName];\n break;\n }\n }\n }\n\n if (isEmpty(result)) {\n return undefined;\n }\n\n if (Array.isArray(result)) {\n return result.map(toTypedValue);\n } else {\n return toTypedValue(result);\n }\n}\n\n/**\n * Removes duplicates in array using FHIRPath equality rules.\n * @param arr The input array.\n * @returns The result array with duplicates removed.\n */\nexport function removeDuplicates(arr: TypedValue[]): TypedValue[] {\n const result: TypedValue[] = [];\n for (const i of arr) {\n let found = false;\n for (const j of result) {\n if (toJsBoolean(fhirPathEquals(i, j))) {\n found = true;\n break;\n }\n }\n if (!found) {\n result.push(i);\n }\n }\n return result;\n}\n\n/**\n * Returns a negated FHIRPath boolean expression.\n * @param input The input array.\n * @returns The negated type value array.\n */\nexport function fhirPathNot(input: TypedValue[]): TypedValue[] {\n return booleanToTypedValue(!toJsBoolean(input));\n}\n\n/**\n * Determines if two arrays are equal according to FHIRPath equality rules.\n * @param x The first array.\n * @param y The second array.\n * @returns FHIRPath true if the arrays are equal.\n */\nexport function fhirPathArrayEquals(x: TypedValue[], y: TypedValue[]): TypedValue[] {\n if (x.length === 0 || y.length === 0) {\n return [];\n }\n if (x.length !== y.length) {\n return booleanToTypedValue(false);\n }\n return booleanToTypedValue(x.every((val, index) => toJsBoolean(fhirPathEquals(val, y[index]))));\n}\n\n/**\n * Determines if two values are equal according to FHIRPath equality rules.\n * @param x The first value.\n * @param y The second value.\n * @returns True if equal.\n */\nexport function fhirPathEquals(x: TypedValue, y: TypedValue): TypedValue[] {\n const xValue = x.value;\n const yValue = y.value;\n if (typeof xValue === 'number' && typeof yValue === 'number') {\n return booleanToTypedValue(Math.abs(xValue - yValue) < 1e-8);\n }\n if (isQuantity(xValue) && isQuantity(yValue)) {\n return booleanToTypedValue(isQuantityEquivalent(xValue, yValue));\n }\n if (typeof xValue === 'object' && typeof yValue === 'object') {\n return booleanToTypedValue(deepEquals(x, y));\n }\n return booleanToTypedValue(xValue === yValue);\n}\n\n/**\n * Determines if two arrays are equivalent according to FHIRPath equality rules.\n * @param x The first array.\n * @param y The second array.\n * @returns FHIRPath true if the arrays are equivalent.\n */\nexport function fhirPathArrayEquivalent(x: TypedValue[], y: TypedValue[]): TypedValue[] {\n if (x.length === 0 && y.length === 0) {\n return booleanToTypedValue(true);\n }\n if (x.length !== y.length) {\n return booleanToTypedValue(false);\n }\n x.sort(fhirPathEquivalentCompare);\n y.sort(fhirPathEquivalentCompare);\n return booleanToTypedValue(x.every((val, index) => toJsBoolean(fhirPathEquivalent(val, y[index]))));\n}\n\n/**\n * Determines if two values are equivalent according to FHIRPath equality rules.\n * @param x The first value.\n * @param y The second value.\n * @returns True if equivalent.\n */\nexport function fhirPathEquivalent(x: TypedValue, y: TypedValue): TypedValue[] {\n const xValue = x.value;\n const yValue = y.value;\n if (typeof xValue === 'number' && typeof yValue === 'number') {\n // Use more generous threshold than equality\n // Decimal: values must be equal, comparison is done on values rounded to the precision of the least precise operand.\n // Trailing zeroes after the decimal are ignored in determining precision.\n return booleanToTypedValue(Math.abs(xValue - yValue) < 0.01);\n }\n if (isQuantity(xValue) && isQuantity(yValue)) {\n return booleanToTypedValue(isQuantityEquivalent(xValue, yValue));\n }\n if (typeof xValue === 'object' && typeof yValue === 'object') {\n return booleanToTypedValue(deepEquals(xValue, yValue));\n }\n if (typeof xValue === 'string' && typeof yValue === 'string') {\n // String: the strings must be the same, ignoring case and locale, and normalizing whitespace\n // (see String Equivalence for more details).\n return booleanToTypedValue(xValue.toLowerCase() === yValue.toLowerCase());\n }\n return booleanToTypedValue(xValue === yValue);\n}\n\n/**\n * Returns the sort order of two values for FHIRPath array equivalence.\n * @param x The first value.\n * @param y The second value.\n * @returns The sort order of the values.\n */\nfunction fhirPathEquivalentCompare(x: TypedValue, y: TypedValue): number {\n const xValue = x.value;\n const yValue = y.value;\n if (typeof xValue === 'number' && typeof yValue === 'number') {\n return xValue - yValue;\n }\n if (typeof xValue === 'string' && typeof yValue === 'string') {\n return xValue.localeCompare(yValue);\n }\n return 0;\n}\n\n/**\n * Determines if the typed value is the desired type.\n * @param typedValue The typed value to check.\n * @param desiredType The desired type name.\n * @returns True if the typed value is of the desired type.\n */\nexport function fhirPathIs(typedValue: TypedValue, desiredType: string): boolean {\n const { value } = typedValue;\n if (value === undefined || value === null) {\n return false;\n }\n\n switch (desiredType) {\n case 'Boolean':\n return typeof value === 'boolean';\n case 'Decimal':\n case 'Integer':\n return typeof value === 'number';\n case 'Date':\n return typeof value === 'string' && !!value.match(/^\\d{4}(-\\d{2}(-\\d{2})?)?/);\n case 'DateTime':\n return typeof value === 'string' && !!value.match(/^\\d{4}(-\\d{2}(-\\d{2})?)?T/);\n case 'Time':\n return typeof value === 'string' && !!value.match(/^T\\d/);\n case 'Period':\n return isPeriod(value);\n case 'Quantity':\n return isQuantity(value);\n default:\n return typeof value === 'object' && value?.resourceType === desiredType;\n }\n}\n\n/**\n * Determines if the input is a Period object.\n * This is heuristic based, as we do not have strong typing at runtime.\n * @param input The input value.\n * @returns True if the input is a period.\n */\nexport function isPeriod(input: unknown): input is Period {\n return !!(input && typeof input === 'object' && 'start' in input);\n}\n\n/**\n * Determines if the input is a Quantity object.\n * This is heuristic based, as we do not have strong typing at runtime.\n * @param input The input value.\n * @returns True if the input is a quantity.\n */\nexport function isQuantity(input: unknown): input is Quantity {\n return !!(input && typeof input === 'object' && 'value' in input && typeof (input as Quantity).value === 'number');\n}\n\nexport function isQuantityEquivalent(x: Quantity, y: Quantity): boolean {\n return (\n Math.abs((x.value as number) - (y.value as number)) < 0.01 &&\n (x.unit === y.unit || x.code === y.code || x.unit === y.code || x.code === y.unit)\n );\n}\n\n/**\n * Resource equality.\n * See: https://dmitripavlutin.com/how-to-compare-objects-in-javascript/#4-deep-equality\n * @param object1 The first object.\n * @param object2 The second object.\n * @returns True if the objects are equal.\n */\nfunction deepEquals<T1 extends object, T2 extends object>(object1: T1, object2: T2): boolean {\n const keys1 = Object.keys(object1) as (keyof T1)[];\n const keys2 = Object.keys(object2) as (keyof T2)[];\n if (keys1.length !== keys2.length) {\n return false;\n }\n for (const key of keys1) {\n const val1 = object1[key] as unknown;\n const val2 = object2[key as unknown as keyof T2] as unknown;\n if (isObject(val1) && isObject(val2)) {\n if (!deepEquals(val1, val2)) {\n return false;\n }\n } else {\n if (val1 !== val2) {\n return false;\n }\n }\n }\n return true;\n}\n\nfunction isObject(obj: unknown): obj is object {\n return obj !== null && typeof obj === 'object';\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.mjs","sources":["../../../src/fhirpath/utils.ts"],"sourcesContent":["import { ElementDefinition, Period, Quantity } from '@medplum/fhirtypes';\nimport { buildTypeName, getElementDefinition, isResource, PropertyType, TypedValue } from '../types';\nimport { capitalize, isEmpty } from '../utils';\n\n/**\n * Returns a single element array with a typed boolean value.\n * @param value The primitive boolean value.\n * @returns Single element array with a typed boolean value.\n */\nexport function booleanToTypedValue(value: boolean): [TypedValue] {\n return [{ type: PropertyType.boolean, value }];\n}\n\n/**\n * Returns a \"best guess\" TypedValue for a given value.\n * @param value The unknown value to check.\n * @returns A \"best guess\" TypedValue for the given value.\n */\nexport function toTypedValue(value: unknown): TypedValue {\n if (value === null || value === undefined) {\n return { type: 'undefined', value: undefined };\n } else if (Number.isSafeInteger(value)) {\n return { type: PropertyType.integer, value };\n } else if (typeof value === 'number') {\n return { type: PropertyType.decimal, value };\n } else if (typeof value === 'boolean') {\n return { type: PropertyType.boolean, value };\n } else if (typeof value === 'string') {\n return { type: PropertyType.string, value };\n } else if (isQuantity(value)) {\n return { type: PropertyType.Quantity, value };\n } else if (isResource(value)) {\n return { type: value.resourceType, value };\n } else {\n return { type: PropertyType.BackboneElement, value };\n }\n}\n\n/**\n * Converts unknown object into a JavaScript boolean.\n * Note that this is different than the FHIRPath \"toBoolean\",\n * which has particular semantics around arrays, empty arrays, and type conversions.\n * @param obj Any value or array of values.\n * @returns The converted boolean value according to FHIRPath rules.\n */\nexport function toJsBoolean(obj: TypedValue[]): boolean {\n return obj.length === 0 ? false : !!obj[0].value;\n}\n\n/**\n * Returns the value of the property and the property type.\n * Some property definitions support multiple types.\n * For example, \"Observation.value[x]\" can be \"valueString\", \"valueInteger\", \"valueQuantity\", etc.\n * According to the spec, there can only be one property for a given element definition.\n * This function returns the value and the type.\n * @param input The base context (FHIR resource or backbone element).\n * @param path The property path.\n * @returns The value of the property and the property type.\n */\nexport function getTypedPropertyValue(input: TypedValue, path: string): TypedValue[] | TypedValue | undefined {\n if (!input.value) {\n return undefined;\n }\n\n const elementDefinition = getElementDefinition(input.type, path);\n if (elementDefinition) {\n const typedResult = getTypedPropertyValueWithSchema(input, path, elementDefinition);\n if (typedResult) {\n return typedResult;\n }\n }\n\n return getTypedPropertyValueWithoutSchema(input, path);\n}\n\n/**\n * Returns the value of the property and the property type using a type schema.\n * @param input The base context (FHIR resource or backbone element).\n * @param path The property path.\n * @param property The property element definition.\n * @returns The value of the property and the property type.\n */\nfunction getTypedPropertyValueWithSchema(\n input: TypedValue,\n path: string,\n property: ElementDefinition\n): TypedValue[] | TypedValue | undefined {\n const types = property.type;\n if (!types || types.length === 0) {\n return undefined;\n }\n\n let resultValue: any = undefined;\n let resultType = 'undefined';\n\n if (types.length === 1) {\n resultValue = input.value[path];\n resultType = types[0].code as string;\n } else {\n for (const type of types) {\n const path2 = path.replace('[x]', '') + capitalize(type.code as string);\n if (path2 in input.value) {\n resultValue = input.value[path2];\n resultType = type.code as string;\n break;\n }\n }\n }\n\n if (isEmpty(resultValue)) {\n return undefined;\n }\n\n if (resultType === 'Element' || resultType === 'BackboneElement') {\n resultType = buildTypeName(property.path?.split('.') as string[]);\n }\n\n if (Array.isArray(resultValue)) {\n return resultValue.map((element) => toTypedValueWithType(element, resultType));\n } else {\n return toTypedValueWithType(resultValue, resultType);\n }\n}\n\nfunction toTypedValueWithType(value: any, type: string): TypedValue {\n if (type === 'Resource' && isResource(value)) {\n type = value.resourceType;\n }\n return { type, value };\n}\n\n/**\n * Returns the value of the property and the property type using a type schema.\n * Note that because the type schema is not available, this function may be inaccurate.\n * In some cases, that is the desired behavior.\n * @param typedValue The base context (FHIR resource or backbone element).\n * @param path The property path.\n * @returns The value of the property and the property type.\n */\nfunction getTypedPropertyValueWithoutSchema(\n typedValue: TypedValue,\n path: string\n): TypedValue[] | TypedValue | undefined {\n const input = typedValue.value;\n if (!input || typeof input !== 'object') {\n return undefined;\n }\n\n let result: any = undefined;\n if (path in input) {\n result = (input as { [key: string]: unknown })[path];\n } else {\n // Only support property names that would be valid types\n // Examples:\n // value + valueString = ok, because \"string\" is valid\n // value + valueDecimal = ok, because \"decimal\" is valid\n // id + identifier = not ok, because \"entifier\" is not a valid type\n // resource + resourceType = not ok, because \"type\" is not a valid type\n //eslint-disable-next-line guard-for-in\n for (const propertyType in PropertyType) {\n const propertyName = path + capitalize(propertyType);\n if (propertyName in input) {\n result = (input as { [key: string]: unknown })[propertyName];\n break;\n }\n }\n }\n\n if (isEmpty(result)) {\n return undefined;\n }\n\n if (Array.isArray(result)) {\n return result.map(toTypedValue);\n } else {\n return toTypedValue(result);\n }\n}\n\n/**\n * Removes duplicates in array using FHIRPath equality rules.\n * @param arr The input array.\n * @returns The result array with duplicates removed.\n */\nexport function removeDuplicates(arr: TypedValue[]): TypedValue[] {\n const result: TypedValue[] = [];\n for (const i of arr) {\n let found = false;\n for (const j of result) {\n if (toJsBoolean(fhirPathEquals(i, j))) {\n found = true;\n break;\n }\n }\n if (!found) {\n result.push(i);\n }\n }\n return result;\n}\n\n/**\n * Returns a negated FHIRPath boolean expression.\n * @param input The input array.\n * @returns The negated type value array.\n */\nexport function fhirPathNot(input: TypedValue[]): TypedValue[] {\n return booleanToTypedValue(!toJsBoolean(input));\n}\n\n/**\n * Determines if two arrays are equal according to FHIRPath equality rules.\n * @param x The first array.\n * @param y The second array.\n * @returns FHIRPath true if the arrays are equal.\n */\nexport function fhirPathArrayEquals(x: TypedValue[], y: TypedValue[]): TypedValue[] {\n if (x.length === 0 || y.length === 0) {\n return [];\n }\n if (x.length !== y.length) {\n return booleanToTypedValue(false);\n }\n return booleanToTypedValue(x.every((val, index) => toJsBoolean(fhirPathEquals(val, y[index]))));\n}\n\n/**\n * Determines if two values are equal according to FHIRPath equality rules.\n * @param x The first value.\n * @param y The second value.\n * @returns True if equal.\n */\nexport function fhirPathEquals(x: TypedValue, y: TypedValue): TypedValue[] {\n const xValue = x.value;\n const yValue = y.value;\n if (typeof xValue === 'number' && typeof yValue === 'number') {\n return booleanToTypedValue(Math.abs(xValue - yValue) < 1e-8);\n }\n if (isQuantity(xValue) && isQuantity(yValue)) {\n return booleanToTypedValue(isQuantityEquivalent(xValue, yValue));\n }\n if (typeof xValue === 'object' && typeof yValue === 'object') {\n return booleanToTypedValue(deepEquals(x, y));\n }\n return booleanToTypedValue(xValue === yValue);\n}\n\n/**\n * Determines if two arrays are equivalent according to FHIRPath equality rules.\n * @param x The first array.\n * @param y The second array.\n * @returns FHIRPath true if the arrays are equivalent.\n */\nexport function fhirPathArrayEquivalent(x: TypedValue[], y: TypedValue[]): TypedValue[] {\n if (x.length === 0 && y.length === 0) {\n return booleanToTypedValue(true);\n }\n if (x.length !== y.length) {\n return booleanToTypedValue(false);\n }\n x.sort(fhirPathEquivalentCompare);\n y.sort(fhirPathEquivalentCompare);\n return booleanToTypedValue(x.every((val, index) => toJsBoolean(fhirPathEquivalent(val, y[index]))));\n}\n\n/**\n * Determines if two values are equivalent according to FHIRPath equality rules.\n * @param x The first value.\n * @param y The second value.\n * @returns True if equivalent.\n */\nexport function fhirPathEquivalent(x: TypedValue, y: TypedValue): TypedValue[] {\n const xValue = x.value;\n const yValue = y.value;\n if (typeof xValue === 'number' && typeof yValue === 'number') {\n // Use more generous threshold than equality\n // Decimal: values must be equal, comparison is done on values rounded to the precision of the least precise operand.\n // Trailing zeroes after the decimal are ignored in determining precision.\n return booleanToTypedValue(Math.abs(xValue - yValue) < 0.01);\n }\n if (isQuantity(xValue) && isQuantity(yValue)) {\n return booleanToTypedValue(isQuantityEquivalent(xValue, yValue));\n }\n if (typeof xValue === 'object' && typeof yValue === 'object') {\n return booleanToTypedValue(deepEquals(xValue, yValue));\n }\n if (typeof xValue === 'string' && typeof yValue === 'string') {\n // String: the strings must be the same, ignoring case and locale, and normalizing whitespace\n // (see String Equivalence for more details).\n return booleanToTypedValue(xValue.toLowerCase() === yValue.toLowerCase());\n }\n return booleanToTypedValue(xValue === yValue);\n}\n\n/**\n * Returns the sort order of two values for FHIRPath array equivalence.\n * @param x The first value.\n * @param y The second value.\n * @returns The sort order of the values.\n */\nfunction fhirPathEquivalentCompare(x: TypedValue, y: TypedValue): number {\n const xValue = x.value;\n const yValue = y.value;\n if (typeof xValue === 'number' && typeof yValue === 'number') {\n return xValue - yValue;\n }\n if (typeof xValue === 'string' && typeof yValue === 'string') {\n return xValue.localeCompare(yValue);\n }\n return 0;\n}\n\n/**\n * Determines if the typed value is the desired type.\n * @param typedValue The typed value to check.\n * @param desiredType The desired type name.\n * @returns True if the typed value is of the desired type.\n */\nexport function fhirPathIs(typedValue: TypedValue, desiredType: string): boolean {\n const { value } = typedValue;\n if (value === undefined || value === null) {\n return false;\n }\n\n switch (desiredType) {\n case 'Boolean':\n return typeof value === 'boolean';\n case 'Decimal':\n case 'Integer':\n return typeof value === 'number';\n case 'Date':\n return typeof value === 'string' && !!value.match(/^\\d{4}(-\\d{2}(-\\d{2})?)?/);\n case 'DateTime':\n return typeof value === 'string' && !!value.match(/^\\d{4}(-\\d{2}(-\\d{2})?)?T/);\n case 'Time':\n return typeof value === 'string' && !!value.match(/^T\\d/);\n case 'Period':\n return isPeriod(value);\n case 'Quantity':\n return isQuantity(value);\n default:\n return typeof value === 'object' && value?.resourceType === desiredType;\n }\n}\n\n/**\n * Determines if the input is a Period object.\n * This is heuristic based, as we do not have strong typing at runtime.\n * @param input The input value.\n * @returns True if the input is a period.\n */\nexport function isPeriod(input: unknown): input is Period {\n return !!(input && typeof input === 'object' && 'start' in input);\n}\n\n/**\n * Determines if the input is a Quantity object.\n * This is heuristic based, as we do not have strong typing at runtime.\n * @param input The input value.\n * @returns True if the input is a quantity.\n */\nexport function isQuantity(input: unknown): input is Quantity {\n return !!(input && typeof input === 'object' && 'value' in input && typeof (input as Quantity).value === 'number');\n}\n\nexport function isQuantityEquivalent(x: Quantity, y: Quantity): boolean {\n return (\n Math.abs((x.value as number) - (y.value as number)) < 0.01 &&\n (x.unit === y.unit || x.code === y.code || x.unit === y.code || x.code === y.unit)\n );\n}\n\n/**\n * Resource equality.\n * See: https://dmitripavlutin.com/how-to-compare-objects-in-javascript/#4-deep-equality\n * @param object1 The first object.\n * @param object2 The second object.\n * @returns True if the objects are equal.\n */\nfunction deepEquals<T1 extends object, T2 extends object>(object1: T1, object2: T2): boolean {\n const keys1 = Object.keys(object1) as (keyof T1)[];\n const keys2 = Object.keys(object2) as (keyof T2)[];\n if (keys1.length !== keys2.length) {\n return false;\n }\n for (const key of keys1) {\n const val1 = object1[key] as unknown;\n const val2 = object2[key as unknown as keyof T2] as unknown;\n if (isObject(val1) && isObject(val2)) {\n if (!deepEquals(val1, val2)) {\n return false;\n }\n } else if (val1 !== val2) {\n return false;\n }\n }\n return true;\n}\n\nfunction isObject(obj: unknown): obj is object {\n return obj !== null && typeof obj === 'object';\n}\n"],"names":[],"mappings":"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"}
@@ -341,7 +341,7 @@ function formatObservationValue(obs) {
341
341
  if ('component' in obs) {
342
342
  return obs.component.map((c) => formatObservationValue(c)).join(' / ');
343
343
  }
344
- if (obs?.valueQuantity) {
344
+ if (obs.valueQuantity) {
345
345
  return formatQuantity(obs.valueQuantity);
346
346
  }
347
347
  if (obs.valueCodeableConcept) {
@@ -1 +1 @@
1
- {"version":3,"file":"format.mjs","sources":["../../src/format.ts"],"sourcesContent":["import {\n Address,\n CodeableConcept,\n Coding,\n HumanName,\n Money,\n Observation,\n ObservationComponent,\n Period,\n Quantity,\n Range,\n Timing,\n} from '@medplum/fhirtypes';\nimport { capitalize } from './utils';\n\nexport interface AddressFormatOptions {\n all?: boolean;\n use?: boolean;\n lineSeparator?: string;\n}\n\nexport interface HumanNameFormatOptions {\n all?: boolean;\n prefix?: boolean;\n suffix?: boolean;\n use?: boolean;\n}\n\n/**\n * Formats a FHIR Address as a string.\n * @param address The address to format.\n * @param options Optional address format options.\n * @returns The formatted address string.\n */\nexport function formatAddress(address: Address, options?: AddressFormatOptions): string {\n const builder = [];\n\n if (address.line) {\n builder.push(...address.line);\n }\n\n if (address.city || address.state || address.postalCode) {\n const cityStateZip = [];\n if (address.city) {\n cityStateZip.push(address.city);\n }\n if (address.state) {\n cityStateZip.push(address.state);\n }\n if (address.postalCode) {\n cityStateZip.push(address.postalCode);\n }\n builder.push(cityStateZip.join(', '));\n }\n\n if (address.use && (options?.all || options?.use)) {\n builder.push('[' + address.use + ']');\n }\n\n return builder.join(options?.lineSeparator || ', ').trim();\n}\n\n/**\n * Formats a FHIR HumanName as a string.\n * @param name The name to format.\n * @param options Optional name format options.\n * @returns The formatted name string.\n */\nexport function formatHumanName(name: HumanName, options?: HumanNameFormatOptions): string {\n const builder = [];\n\n if (name.prefix && options?.prefix !== false) {\n builder.push(...name.prefix);\n }\n\n if (name.given) {\n builder.push(...name.given);\n }\n\n if (name.family) {\n builder.push(name.family);\n }\n\n if (name.suffix && options?.suffix !== false) {\n builder.push(...name.suffix);\n }\n\n if (name.use && (options?.all || options?.use)) {\n builder.push('[' + name.use + ']');\n }\n\n return builder.join(' ').trim();\n}\n\n/**\n * Formats the given name portion of a FHIR HumanName element.\n * @param name The name to format.\n * @returns The formatted given name string.\n */\nexport function formatGivenName(name: HumanName): string {\n const builder: string[] = [];\n if (name.given) {\n builder.push(...name.given);\n }\n return builder.join(' ').trim();\n}\n\n/**\n * Formats the family name portion of a FHIR HumanName element.\n * @param name The name to format.\n * @returns The formatted family name string.\n */\nexport function formatFamilyName(name: HumanName): string {\n return name.family || '';\n}\n\n/**\n * Returns true if the given date object is a valid date.\n * Dates can be invalid if created by parsing an invalid string.\n * @param date A date object.\n * @returns Returns true if the date is a valid date.\n */\nexport function isValidDate(date: Date): boolean {\n return date instanceof Date && !isNaN(date.getTime());\n}\n\n/**\n * Formats a FHIR date string as a human readable string.\n * Handles missing values and invalid dates.\n * @param date The date to format.\n * @param locales Optional locales.\n * @param options Optional date format options.\n * @returns The formatted date string.\n */\nexport function formatDate(\n date: string | undefined,\n locales?: Intl.LocalesArgument,\n options?: Intl.DateTimeFormatOptions | undefined\n): string {\n if (!date) {\n return '';\n }\n const d = new Date(date);\n if (!isValidDate(d)) {\n return '';\n }\n d.setUTCHours(0, 0, 0, 0);\n return d.toLocaleDateString(locales, { timeZone: 'UTC', ...options });\n}\n\n/**\n * Formats a FHIR time string as a human readable string.\n * Handles missing values and invalid dates.\n * @param time The date to format.\n * @param locales Optional locales.\n * @param options Optional time format options.\n * @returns The formatted time string.\n */\nexport function formatTime(\n time: string | undefined,\n locales?: Intl.LocalesArgument,\n options?: Intl.DateTimeFormatOptions | undefined\n): string {\n if (!time) {\n return '';\n }\n const d = new Date('2000-01-01T' + time + 'Z');\n if (!isValidDate(d)) {\n return '';\n }\n return d.toLocaleTimeString(locales, options);\n}\n\n/**\n * Formats a FHIR dateTime string as a human readable string.\n * Handles missing values and invalid dates.\n * @param dateTime The dateTime to format.\n * @param locales Optional locales.\n * @param options Optional dateTime format options.\n * @returns The formatted dateTime string.\n */\nexport function formatDateTime(\n dateTime: string | undefined,\n locales?: Intl.LocalesArgument,\n options?: Intl.DateTimeFormatOptions | undefined\n): string {\n if (!dateTime) {\n return '';\n }\n const d = new Date(dateTime);\n if (!isValidDate(d)) {\n return '';\n }\n return d.toLocaleString(locales, options);\n}\n\n/**\n * Formats a FHIR Period as a human readable string.\n * @param period The period to format.\n * @param locales Optional locales.\n * @param options Optional period format options.\n * @returns The formatted period string.\n */\nexport function formatPeriod(\n period: Period | undefined,\n locales?: Intl.LocalesArgument,\n options?: Intl.DateTimeFormatOptions | undefined\n): string {\n if (!period || (!period.start && !period.end)) {\n return '';\n }\n return formatDateTime(period.start, locales, options) + ' - ' + formatDateTime(period.end, locales, options);\n}\n\nconst unitAdverbForm: Record<string, string> = {\n s: 'every second',\n min: 'every minute',\n h: 'hourly',\n d: 'daily',\n wk: 'weekly',\n mo: 'monthly',\n a: 'annually',\n};\n\nconst singularUnits: Record<string, string> = {\n s: 'second',\n min: 'minute',\n h: 'hour',\n d: 'day',\n wk: 'week',\n mo: 'month',\n a: 'year',\n};\n\nconst pluralUnits: Record<string, string> = {\n s: 'seconds',\n min: 'minutes',\n h: 'hours',\n d: 'days',\n wk: 'weeks',\n mo: 'months',\n a: 'years',\n};\n\n/**\n * Formats a FHIR Timing as a human readable string.\n * @param timing The timing to format.\n * @returns The formatted timing string.\n */\nexport function formatTiming(timing: Timing | undefined): string {\n if (!timing) {\n return '';\n }\n\n const builder: string[] = [];\n\n if (timing.repeat?.periodUnit) {\n const frequency = timing.repeat.frequency || 1;\n const period = timing.repeat.period || 1;\n const periodUnit = timing.repeat.periodUnit;\n\n if (frequency === 1 && period === 1) {\n builder.push(unitAdverbForm[periodUnit]);\n } else {\n if (frequency === 1) {\n builder.push('once');\n } else {\n builder.push(frequency + ' times');\n }\n\n if (period === 1) {\n builder.push('per ' + singularUnits[periodUnit]);\n } else {\n builder.push('per ' + period + ' ' + pluralUnits[periodUnit]);\n }\n }\n\n if (timing.repeat.dayOfWeek) {\n builder.push('on ' + timing.repeat.dayOfWeek.map(capitalize).join(', '));\n }\n\n if (timing.repeat.timeOfDay) {\n builder.push('at ' + timing.repeat.timeOfDay.map((t) => formatTime(t)).join(', '));\n }\n }\n\n if (timing.event) {\n builder.push(timing.event.map((d) => formatDateTime(d)).join(', '));\n }\n\n return capitalize(builder.join(' ').trim());\n}\n\n/**\n * Returns a human-readable string for a FHIR Range datatype, taking into account one-sided ranges\n * @param range A FHIR Range element\n * @param precision Number of decimal places to display in the rendered quantity values\n * @param exclusive If true, one-sided ranges will be rendered with the '>' or '<' bounds rather than '>=' or '<='\n * @returns A human-readable string representation of the Range\n */\nexport function formatRange(range: Range | undefined, precision?: number, exclusive = false): string {\n if (exclusive && precision === undefined) {\n throw new Error('Precision must be specified for exclusive ranges');\n }\n\n // Extract high and low range endpoints, explicitly ignoring any comparator\n // since Range uses SimpleQuantity variants (see http://www.hl7.org/fhir/datatypes.html#Range)\n const low = range?.low && { ...range.low, comparator: undefined };\n const high = range?.high && { ...range.high, comparator: undefined };\n if (low?.value === undefined && high?.value === undefined) {\n return '';\n }\n\n if (low?.value !== undefined && high?.value === undefined) {\n // Lower bound only\n if (exclusive && precision !== undefined) {\n low.value = preciseDecrement(low.value, precision);\n return `> ${formatQuantity(low, precision)}`;\n }\n return `>= ${formatQuantity(low, precision)}`;\n } else if (low?.value === undefined && high?.value !== undefined) {\n // Upper bound only\n if (exclusive && precision !== undefined) {\n high.value = preciseIncrement(high.value, precision);\n return `< ${formatQuantity(high, precision)}`;\n }\n return `<= ${formatQuantity(high, precision)}`;\n } else {\n // Double-sided range\n if (low?.unit === high?.unit) {\n delete low?.unit; // Format like \"X - Y units\" instead of \"X units - Y units\"\n }\n return `${formatQuantity(low, precision)} - ${formatQuantity(high, precision)}`;\n }\n}\n\n/**\n * Returns a human-readable string for a FHIR Quantity datatype, taking into account units and comparators\n * @param quantity A FHIR Quantity element\n * @param precision Number of decimal places to display in the rendered quantity values\n * @returns A human-readable string representation of the Quantity\n */\nexport function formatQuantity(quantity: Quantity | undefined, precision?: number): string {\n if (!quantity) {\n return '';\n }\n\n const result = [];\n\n if (quantity.comparator) {\n result.push(quantity.comparator);\n result.push(' ');\n }\n\n if (quantity.value !== undefined) {\n if (precision !== undefined) {\n result.push(quantity.value.toFixed(precision));\n } else {\n result.push(quantity.value);\n }\n }\n\n if (quantity.unit) {\n if (quantity.unit !== '%' && result[result.length - 1] !== ' ') {\n result.push(' ');\n }\n result.push(quantity.unit);\n }\n\n return result.join('').trim();\n}\n\nexport function formatMoney(money: Money | undefined): string {\n if (money?.value === undefined) {\n return '';\n }\n\n return money.value.toLocaleString(undefined, {\n style: 'currency',\n currency: money.currency || 'USD',\n currencyDisplay: 'narrowSymbol',\n });\n}\n\n/**\n * Formats a CodeableConcept element as a string.\n * @param codeableConcept A FHIR CodeableConcept element\n * @returns The codeable concept as a string.\n */\nexport function formatCodeableConcept(codeableConcept: CodeableConcept | undefined): string {\n if (!codeableConcept) {\n return '';\n }\n if (codeableConcept.text) {\n return codeableConcept.text;\n }\n if (codeableConcept.coding) {\n return codeableConcept.coding.map((c) => formatCoding(c)).join(', ');\n }\n return '';\n}\n\n/**\n * Formats a Coding element as a string.\n * @param coding A FHIR Coding element\n * @returns The coding as a string.\n */\nexport function formatCoding(coding: Coding | undefined): string {\n return coding?.display || coding?.code || '';\n}\n\n/**\n * Formats a FHIR Observation resource value as a string.\n * @param obs A FHIR Observation resource.\n * @returns A human-readable string representation of the Observation.\n */\nexport function formatObservationValue(obs: Observation | ObservationComponent | undefined): string {\n if (!obs) {\n return '';\n }\n\n if ('component' in obs) {\n return (obs.component as ObservationComponent[]).map((c) => formatObservationValue(c)).join(' / ');\n }\n\n if (obs?.valueQuantity) {\n return formatQuantity(obs.valueQuantity);\n }\n\n if (obs.valueCodeableConcept) {\n return formatCodeableConcept(obs.valueCodeableConcept);\n }\n\n if (obs.valueString) {\n return obs.valueString;\n }\n\n return '';\n}\n\n/**\n * Returns the input number increased by the `n` units of the specified precision\n * @param a The input number.\n * @param precision The precision in number of digits.\n * @param n (default 1) The number of units to add.\n * @returns The result of the increment.\n */\nfunction preciseIncrement(a: number, precision: number, n = 1): number {\n return (toPreciseInteger(a, precision) + n) * Math.pow(10, -precision);\n}\n\n/**\n * Returns the input number decreased by the `n` units of the specified precision\n * @param a The input number.\n * @param precision The precision in number of digits.\n * @param n (default 1) The number of units to subtract.\n * @returns The result of the decrement.\n */\nfunction preciseDecrement(a: number, precision: number, n = 1): number {\n return (toPreciseInteger(a, precision) - n) * Math.pow(10, -precision);\n}\n\n/**\n * Returns an integer representation of the number with the given precision.\n * For example, if precision is 2, then 1.2345 will be returned as 123.\n * @param a The number.\n * @param precision Optional precision in number of digits.\n * @returns The integer with the given precision.\n */\nfunction toPreciseInteger(a: number, precision?: number): number {\n if (precision === undefined) {\n return a;\n }\n return Math.round(a * Math.pow(10, precision));\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"format.mjs","sources":["../../src/format.ts"],"sourcesContent":["import {\n Address,\n CodeableConcept,\n Coding,\n HumanName,\n Money,\n Observation,\n ObservationComponent,\n Period,\n Quantity,\n Range,\n Timing,\n} from '@medplum/fhirtypes';\nimport { capitalize } from './utils';\n\nexport interface AddressFormatOptions {\n all?: boolean;\n use?: boolean;\n lineSeparator?: string;\n}\n\nexport interface HumanNameFormatOptions {\n all?: boolean;\n prefix?: boolean;\n suffix?: boolean;\n use?: boolean;\n}\n\n/**\n * Formats a FHIR Address as a string.\n * @param address The address to format.\n * @param options Optional address format options.\n * @returns The formatted address string.\n */\nexport function formatAddress(address: Address, options?: AddressFormatOptions): string {\n const builder = [];\n\n if (address.line) {\n builder.push(...address.line);\n }\n\n if (address.city || address.state || address.postalCode) {\n const cityStateZip = [];\n if (address.city) {\n cityStateZip.push(address.city);\n }\n if (address.state) {\n cityStateZip.push(address.state);\n }\n if (address.postalCode) {\n cityStateZip.push(address.postalCode);\n }\n builder.push(cityStateZip.join(', '));\n }\n\n if (address.use && (options?.all || options?.use)) {\n builder.push('[' + address.use + ']');\n }\n\n return builder.join(options?.lineSeparator || ', ').trim();\n}\n\n/**\n * Formats a FHIR HumanName as a string.\n * @param name The name to format.\n * @param options Optional name format options.\n * @returns The formatted name string.\n */\nexport function formatHumanName(name: HumanName, options?: HumanNameFormatOptions): string {\n const builder = [];\n\n if (name.prefix && options?.prefix !== false) {\n builder.push(...name.prefix);\n }\n\n if (name.given) {\n builder.push(...name.given);\n }\n\n if (name.family) {\n builder.push(name.family);\n }\n\n if (name.suffix && options?.suffix !== false) {\n builder.push(...name.suffix);\n }\n\n if (name.use && (options?.all || options?.use)) {\n builder.push('[' + name.use + ']');\n }\n\n return builder.join(' ').trim();\n}\n\n/**\n * Formats the given name portion of a FHIR HumanName element.\n * @param name The name to format.\n * @returns The formatted given name string.\n */\nexport function formatGivenName(name: HumanName): string {\n const builder: string[] = [];\n if (name.given) {\n builder.push(...name.given);\n }\n return builder.join(' ').trim();\n}\n\n/**\n * Formats the family name portion of a FHIR HumanName element.\n * @param name The name to format.\n * @returns The formatted family name string.\n */\nexport function formatFamilyName(name: HumanName): string {\n return name.family || '';\n}\n\n/**\n * Returns true if the given date object is a valid date.\n * Dates can be invalid if created by parsing an invalid string.\n * @param date A date object.\n * @returns Returns true if the date is a valid date.\n */\nexport function isValidDate(date: Date): boolean {\n return date instanceof Date && !isNaN(date.getTime());\n}\n\n/**\n * Formats a FHIR date string as a human readable string.\n * Handles missing values and invalid dates.\n * @param date The date to format.\n * @param locales Optional locales.\n * @param options Optional date format options.\n * @returns The formatted date string.\n */\nexport function formatDate(\n date: string | undefined,\n locales?: Intl.LocalesArgument,\n options?: Intl.DateTimeFormatOptions | undefined\n): string {\n if (!date) {\n return '';\n }\n const d = new Date(date);\n if (!isValidDate(d)) {\n return '';\n }\n d.setUTCHours(0, 0, 0, 0);\n return d.toLocaleDateString(locales, { timeZone: 'UTC', ...options });\n}\n\n/**\n * Formats a FHIR time string as a human readable string.\n * Handles missing values and invalid dates.\n * @param time The date to format.\n * @param locales Optional locales.\n * @param options Optional time format options.\n * @returns The formatted time string.\n */\nexport function formatTime(\n time: string | undefined,\n locales?: Intl.LocalesArgument,\n options?: Intl.DateTimeFormatOptions | undefined\n): string {\n if (!time) {\n return '';\n }\n const d = new Date('2000-01-01T' + time + 'Z');\n if (!isValidDate(d)) {\n return '';\n }\n return d.toLocaleTimeString(locales, options);\n}\n\n/**\n * Formats a FHIR dateTime string as a human readable string.\n * Handles missing values and invalid dates.\n * @param dateTime The dateTime to format.\n * @param locales Optional locales.\n * @param options Optional dateTime format options.\n * @returns The formatted dateTime string.\n */\nexport function formatDateTime(\n dateTime: string | undefined,\n locales?: Intl.LocalesArgument,\n options?: Intl.DateTimeFormatOptions | undefined\n): string {\n if (!dateTime) {\n return '';\n }\n const d = new Date(dateTime);\n if (!isValidDate(d)) {\n return '';\n }\n return d.toLocaleString(locales, options);\n}\n\n/**\n * Formats a FHIR Period as a human readable string.\n * @param period The period to format.\n * @param locales Optional locales.\n * @param options Optional period format options.\n * @returns The formatted period string.\n */\nexport function formatPeriod(\n period: Period | undefined,\n locales?: Intl.LocalesArgument,\n options?: Intl.DateTimeFormatOptions | undefined\n): string {\n if (!period || (!period.start && !period.end)) {\n return '';\n }\n return formatDateTime(period.start, locales, options) + ' - ' + formatDateTime(period.end, locales, options);\n}\n\nconst unitAdverbForm: Record<string, string> = {\n s: 'every second',\n min: 'every minute',\n h: 'hourly',\n d: 'daily',\n wk: 'weekly',\n mo: 'monthly',\n a: 'annually',\n};\n\nconst singularUnits: Record<string, string> = {\n s: 'second',\n min: 'minute',\n h: 'hour',\n d: 'day',\n wk: 'week',\n mo: 'month',\n a: 'year',\n};\n\nconst pluralUnits: Record<string, string> = {\n s: 'seconds',\n min: 'minutes',\n h: 'hours',\n d: 'days',\n wk: 'weeks',\n mo: 'months',\n a: 'years',\n};\n\n/**\n * Formats a FHIR Timing as a human readable string.\n * @param timing The timing to format.\n * @returns The formatted timing string.\n */\nexport function formatTiming(timing: Timing | undefined): string {\n if (!timing) {\n return '';\n }\n\n const builder: string[] = [];\n\n if (timing.repeat?.periodUnit) {\n const frequency = timing.repeat.frequency || 1;\n const period = timing.repeat.period || 1;\n const periodUnit = timing.repeat.periodUnit;\n\n if (frequency === 1 && period === 1) {\n builder.push(unitAdverbForm[periodUnit]);\n } else {\n if (frequency === 1) {\n builder.push('once');\n } else {\n builder.push(frequency + ' times');\n }\n\n if (period === 1) {\n builder.push('per ' + singularUnits[periodUnit]);\n } else {\n builder.push('per ' + period + ' ' + pluralUnits[periodUnit]);\n }\n }\n\n if (timing.repeat.dayOfWeek) {\n builder.push('on ' + timing.repeat.dayOfWeek.map(capitalize).join(', '));\n }\n\n if (timing.repeat.timeOfDay) {\n builder.push('at ' + timing.repeat.timeOfDay.map((t) => formatTime(t)).join(', '));\n }\n }\n\n if (timing.event) {\n builder.push(timing.event.map((d) => formatDateTime(d)).join(', '));\n }\n\n return capitalize(builder.join(' ').trim());\n}\n\n/**\n * Returns a human-readable string for a FHIR Range datatype, taking into account one-sided ranges\n * @param range A FHIR Range element\n * @param precision Number of decimal places to display in the rendered quantity values\n * @param exclusive If true, one-sided ranges will be rendered with the '>' or '<' bounds rather than '>=' or '<='\n * @returns A human-readable string representation of the Range\n */\nexport function formatRange(range: Range | undefined, precision?: number, exclusive = false): string {\n if (exclusive && precision === undefined) {\n throw new Error('Precision must be specified for exclusive ranges');\n }\n\n // Extract high and low range endpoints, explicitly ignoring any comparator\n // since Range uses SimpleQuantity variants (see http://www.hl7.org/fhir/datatypes.html#Range)\n const low = range?.low && { ...range.low, comparator: undefined };\n const high = range?.high && { ...range.high, comparator: undefined };\n if (low?.value === undefined && high?.value === undefined) {\n return '';\n }\n\n if (low?.value !== undefined && high?.value === undefined) {\n // Lower bound only\n if (exclusive && precision !== undefined) {\n low.value = preciseDecrement(low.value, precision);\n return `> ${formatQuantity(low, precision)}`;\n }\n return `>= ${formatQuantity(low, precision)}`;\n } else if (low?.value === undefined && high?.value !== undefined) {\n // Upper bound only\n if (exclusive && precision !== undefined) {\n high.value = preciseIncrement(high.value, precision);\n return `< ${formatQuantity(high, precision)}`;\n }\n return `<= ${formatQuantity(high, precision)}`;\n } else {\n // Double-sided range\n if (low?.unit === high?.unit) {\n delete low?.unit; // Format like \"X - Y units\" instead of \"X units - Y units\"\n }\n return `${formatQuantity(low, precision)} - ${formatQuantity(high, precision)}`;\n }\n}\n\n/**\n * Returns a human-readable string for a FHIR Quantity datatype, taking into account units and comparators\n * @param quantity A FHIR Quantity element\n * @param precision Number of decimal places to display in the rendered quantity values\n * @returns A human-readable string representation of the Quantity\n */\nexport function formatQuantity(quantity: Quantity | undefined, precision?: number): string {\n if (!quantity) {\n return '';\n }\n\n const result = [];\n\n if (quantity.comparator) {\n result.push(quantity.comparator);\n result.push(' ');\n }\n\n if (quantity.value !== undefined) {\n if (precision !== undefined) {\n result.push(quantity.value.toFixed(precision));\n } else {\n result.push(quantity.value);\n }\n }\n\n if (quantity.unit) {\n if (quantity.unit !== '%' && result[result.length - 1] !== ' ') {\n result.push(' ');\n }\n result.push(quantity.unit);\n }\n\n return result.join('').trim();\n}\n\nexport function formatMoney(money: Money | undefined): string {\n if (money?.value === undefined) {\n return '';\n }\n\n return money.value.toLocaleString(undefined, {\n style: 'currency',\n currency: money.currency || 'USD',\n currencyDisplay: 'narrowSymbol',\n });\n}\n\n/**\n * Formats a CodeableConcept element as a string.\n * @param codeableConcept A FHIR CodeableConcept element\n * @returns The codeable concept as a string.\n */\nexport function formatCodeableConcept(codeableConcept: CodeableConcept | undefined): string {\n if (!codeableConcept) {\n return '';\n }\n if (codeableConcept.text) {\n return codeableConcept.text;\n }\n if (codeableConcept.coding) {\n return codeableConcept.coding.map((c) => formatCoding(c)).join(', ');\n }\n return '';\n}\n\n/**\n * Formats a Coding element as a string.\n * @param coding A FHIR Coding element\n * @returns The coding as a string.\n */\nexport function formatCoding(coding: Coding | undefined): string {\n return coding?.display || coding?.code || '';\n}\n\n/**\n * Formats a FHIR Observation resource value as a string.\n * @param obs A FHIR Observation resource.\n * @returns A human-readable string representation of the Observation.\n */\nexport function formatObservationValue(obs: Observation | ObservationComponent | undefined): string {\n if (!obs) {\n return '';\n }\n\n if ('component' in obs) {\n return (obs.component as ObservationComponent[]).map((c) => formatObservationValue(c)).join(' / ');\n }\n\n if (obs.valueQuantity) {\n return formatQuantity(obs.valueQuantity);\n }\n\n if (obs.valueCodeableConcept) {\n return formatCodeableConcept(obs.valueCodeableConcept);\n }\n\n if (obs.valueString) {\n return obs.valueString;\n }\n\n return '';\n}\n\n/**\n * Returns the input number increased by the `n` units of the specified precision\n * @param a The input number.\n * @param precision The precision in number of digits.\n * @param n (default 1) The number of units to add.\n * @returns The result of the increment.\n */\nfunction preciseIncrement(a: number, precision: number, n = 1): number {\n return (toPreciseInteger(a, precision) + n) * Math.pow(10, -precision);\n}\n\n/**\n * Returns the input number decreased by the `n` units of the specified precision\n * @param a The input number.\n * @param precision The precision in number of digits.\n * @param n (default 1) The number of units to subtract.\n * @returns The result of the decrement.\n */\nfunction preciseDecrement(a: number, precision: number, n = 1): number {\n return (toPreciseInteger(a, precision) - n) * Math.pow(10, -precision);\n}\n\n/**\n * Returns an integer representation of the number with the given precision.\n * For example, if precision is 2, then 1.2345 will be returned as 123.\n * @param a The number.\n * @param precision Optional precision in number of digits.\n * @returns The integer with the given precision.\n */\nfunction toPreciseInteger(a: number, precision?: number): number {\n if (precision === undefined) {\n return a;\n }\n return Math.round(a * Math.pow(10, precision));\n}\n"],"names":[],"mappings":"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"}
package/dist/esm/hl7.mjs CHANGED
@@ -226,12 +226,12 @@ function parseHl7Date(hl7Date, options) {
226
226
  return undefined;
227
227
  }
228
228
  options = { ...{ seconds: true, tzOffset: 'Z' }, ...options };
229
- const year = Number.parseInt(hl7Date.substring(0, 4));
230
- const month = Number.parseInt(hl7Date.substring(4, 6));
231
- const date = Number.parseInt(hl7Date.substring(6, 8));
232
- const hours = Number.parseInt(hl7Date.substring(8, 10));
233
- const minutes = Number.parseInt(hl7Date.substring(10, 12));
234
- const seconds = options.seconds ? Number.parseInt(hl7Date.substring(12, 14)) : 0;
229
+ const year = Number.parseInt(hl7Date.substring(0, 4), 10);
230
+ const month = Number.parseInt(hl7Date.substring(4, 6), 10);
231
+ const date = Number.parseInt(hl7Date.substring(6, 8), 10);
232
+ const hours = Number.parseInt(hl7Date.substring(8, 10), 10);
233
+ const minutes = Number.parseInt(hl7Date.substring(10, 12), 10);
234
+ const seconds = options.seconds ? Number.parseInt(hl7Date.substring(12, 14), 10) : 0;
235
235
  return `${pad2(year)}-${pad2(month)}-${pad2(date)}T${pad2(hours)}:${pad2(minutes)}:${pad2(seconds)}.000${options.tzOffset}`;
236
236
  }
237
237
  function pad2(n) {
@@ -1 +1 @@
1
- {"version":3,"file":"hl7.mjs","sources":["../../src/hl7.ts"],"sourcesContent":["import { isStringArray } from './utils';\n\n/**\n * The Hl7Context class represents the parsing context for an HL7 message.\n *\n * MSH-1:\n * https://hl7-definition.caristix.com/v2/HL7v2.6/Fields/MSH.1\n *\n * MSH-2:\n * https://hl7-definition.caristix.com/v2/HL7v2.6/Fields/MSH.2\n *\n * See this tutorial on MSH, and why it's a bad idea to use anything other than the default values:\n * https://www.hl7soup.com/HL7TutorialMSH.html\n */\nexport class Hl7Context {\n constructor(\n public readonly segmentSeparator = '\\r',\n public readonly fieldSeparator = '|',\n public readonly componentSeparator = '^',\n public readonly repetitionSeparator = '~',\n public readonly escapeCharacter = '\\\\',\n public readonly subcomponentSeparator = '&'\n ) {}\n\n /**\n * Returns the MSH-2 field value based on the configured separators.\n * @returns The HL7 MSH-2 field value.\n */\n getMsh2(): string {\n return (\n this.fieldSeparator +\n this.componentSeparator +\n this.repetitionSeparator +\n this.escapeCharacter +\n this.subcomponentSeparator\n );\n }\n}\n\n/**\n * The Hl7Message class represents one HL7 message.\n * A message is a collection of segments.\n */\nexport class Hl7Message {\n readonly context: Hl7Context;\n readonly segments: Hl7Segment[];\n\n /**\n * Creates a new HL7 message.\n * @param segments The HL7 segments.\n * @param context Optional HL7 parsing context.\n */\n constructor(segments: Hl7Segment[], context = new Hl7Context()) {\n this.context = context;\n this.segments = segments;\n }\n\n /**\n * Returns an HL7 segment by index or by name.\n * @param index The HL7 segment index or name.\n * @returns The HL7 segment if found; otherwise, undefined.\n */\n get(index: number | string): Hl7Segment | undefined {\n if (typeof index === 'number') {\n return this.segments[index];\n }\n return this.segments.find((s) => s.name === index);\n }\n\n /**\n * Returns all HL7 segments of a given name.\n * @param name The HL7 segment name.\n * @returns An array of HL7 segments with the specified name.\n */\n getAll(name: string): Hl7Segment[] {\n return this.segments.filter((s) => s.name === name);\n }\n\n /**\n * Returns the HL7 message as a string.\n * @returns The HL7 message as a string.\n */\n toString(): string {\n return this.segments.map((s) => s.toString()).join(this.context.segmentSeparator);\n }\n\n /**\n * Returns an HL7 \"ACK\" (acknowledgement) message for this message.\n * @returns The HL7 \"ACK\" message.\n */\n buildAck(): Hl7Message {\n const now = new Date();\n const msh = this.get('MSH');\n const sendingApp = msh?.get(2)?.toString() || '';\n const sendingFacility = msh?.get(3)?.toString() || '';\n const receivingApp = msh?.get(4)?.toString() || '';\n const receivingFacility = msh?.get(5)?.toString() || '';\n const controlId = msh?.get(9)?.toString() || '';\n const versionId = msh?.get(12)?.toString() || '2.5.1';\n\n return new Hl7Message([\n new Hl7Segment(\n [\n 'MSH',\n this.context.getMsh2(),\n receivingApp,\n receivingFacility,\n sendingApp,\n sendingFacility,\n now.toISOString(),\n '',\n 'ACK',\n now.getTime().toString(),\n 'P',\n versionId,\n ],\n this.context\n ),\n new Hl7Segment(['MSA', 'AA', controlId, 'OK'], this.context),\n ]);\n }\n\n /**\n * Parses an HL7 message string into an Hl7Message object.\n * @param text The HL7 message text.\n * @returns The parsed HL7 message.\n */\n static parse(text: string): Hl7Message {\n if (!text.startsWith('MSH')) {\n const err = new Error('Invalid HL7 message');\n (err as any).type = 'entity.parse.failed';\n throw err;\n }\n const context = new Hl7Context(\n '\\r',\n text.charAt(3), // Field separator, recommended \"|\"\n text.charAt(4), // Component separator, recommended \"^\"\n text.charAt(5), // Repetition separator, recommended \"~\"\n text.charAt(6), // Escape character, recommended \"\\\"\n text.charAt(7) // Subcomponent separator, recommended \"&\"\n );\n return new Hl7Message(\n text.split(/[\\r\\n]+/).map((line) => Hl7Segment.parse(line, context)),\n context\n );\n }\n}\n\n/**\n * The Hl7Segment class represents one HL7 segment.\n * A segment is a collection of fields.\n * The name field is the first field.\n */\nexport class Hl7Segment {\n readonly context: Hl7Context;\n readonly name: string;\n readonly fields: Hl7Field[];\n\n /**\n * Creates a new HL7 segment.\n * @param fields The HL7 fields.\n * @param context Optional HL7 parsing context.\n */\n constructor(fields: Hl7Field[] | string[], context = new Hl7Context()) {\n this.context = context;\n if (isStringArray(fields)) {\n this.fields = fields.map((f) => Hl7Field.parse(f));\n } else {\n this.fields = fields;\n }\n this.name = this.fields[0].components[0][0];\n }\n\n /**\n * Returns an HL7 field by index.\n * @param index The HL7 field index.\n * @returns The HL7 field.\n */\n get(index: number): Hl7Field {\n return this.fields[index];\n }\n\n /**\n * Returns the HL7 segment as a string.\n * @returns The HL7 segment as a string.\n */\n toString(): string {\n return this.fields.map((f) => f.toString()).join(this.context.fieldSeparator);\n }\n\n /**\n * Parses an HL7 segment string into an Hl7Segment object.\n * @param text The HL7 segment text.\n * @param context Optional HL7 parsing context.\n * @returns The parsed HL7 segment.\n */\n static parse(text: string, context = new Hl7Context()): Hl7Segment {\n return new Hl7Segment(\n text.split(context.fieldSeparator).map((f) => Hl7Field.parse(f, context)),\n context\n );\n }\n}\n\n/**\n * The Hl7Field class represents one HL7 field.\n * A field is a collection of components.\n */\nexport class Hl7Field {\n readonly context: Hl7Context;\n readonly components: string[][];\n\n /**\n * Creates a new HL7 field.\n * @param components The HL7 components.\n * @param context Optional HL7 parsing context.\n */\n constructor(components: string[][], context = new Hl7Context()) {\n this.context = context;\n this.components = components;\n }\n\n /**\n * Returns an HL7 component by index.\n * @param component The component index.\n * @param subcomponent Optional subcomponent index.\n * @param repetition Optional repetition index.\n * @returns The string value of the specified component.\n */\n get(component: number, subcomponent?: number, repetition = 0): string {\n let value = this.components[repetition][component] || '';\n\n if (subcomponent !== undefined) {\n value = value.split(this.context.subcomponentSeparator)[subcomponent] || '';\n }\n\n return value;\n }\n\n /**\n * Returns the HL7 field as a string.\n * @returns The HL7 field as a string.\n */\n toString(): string {\n return this.components.map((r) => r.join(this.context.componentSeparator)).join(this.context.repetitionSeparator);\n }\n\n /**\n * Parses an HL7 field string into an Hl7Field object.\n * @param text The HL7 field text.\n * @param context Optional HL7 parsing context.\n * @returns The parsed HL7 field.\n */\n static parse(text: string, context = new Hl7Context()): Hl7Field {\n return new Hl7Field(\n text.split(context.repetitionSeparator).map((r) => r.split(context.componentSeparator)),\n context\n );\n }\n}\n\ninterface Hl7DateParseOptions {\n seconds?: boolean;\n tzOffset?: string;\n}\n\n/**\n * Returns a formatted string representing the date in ISO-8601 format.\n * @param hl7Date Date string.\n * @param options Optional configuration Object\n * @returns The date in ISO-8601 format.\n */\nexport function parseHl7Date(hl7Date: string | undefined, options?: Hl7DateParseOptions): string | undefined {\n if (!hl7Date) {\n return undefined;\n }\n\n options = { ...{ seconds: true, tzOffset: 'Z' }, ...options };\n\n const year = Number.parseInt(hl7Date.substring(0, 4));\n const month = Number.parseInt(hl7Date.substring(4, 6));\n const date = Number.parseInt(hl7Date.substring(6, 8));\n const hours = Number.parseInt(hl7Date.substring(8, 10));\n const minutes = Number.parseInt(hl7Date.substring(10, 12));\n\n const seconds = options.seconds ? Number.parseInt(hl7Date.substring(12, 14)) : 0;\n\n return `${pad2(year)}-${pad2(month)}-${pad2(date)}T${pad2(hours)}:${pad2(minutes)}:${pad2(seconds)}.000${\n options.tzOffset\n }`;\n}\n\nfunction pad2(n: number): string {\n return n.toString().padStart(2, '0');\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hl7.mjs","sources":["../../src/hl7.ts"],"sourcesContent":["import { isStringArray } from './utils';\n\n/**\n * The Hl7Context class represents the parsing context for an HL7 message.\n *\n * MSH-1:\n * https://hl7-definition.caristix.com/v2/HL7v2.6/Fields/MSH.1\n *\n * MSH-2:\n * https://hl7-definition.caristix.com/v2/HL7v2.6/Fields/MSH.2\n *\n * See this tutorial on MSH, and why it's a bad idea to use anything other than the default values:\n * https://www.hl7soup.com/HL7TutorialMSH.html\n */\nexport class Hl7Context {\n constructor(\n public readonly segmentSeparator = '\\r',\n public readonly fieldSeparator = '|',\n public readonly componentSeparator = '^',\n public readonly repetitionSeparator = '~',\n public readonly escapeCharacter = '\\\\',\n public readonly subcomponentSeparator = '&'\n ) {}\n\n /**\n * Returns the MSH-2 field value based on the configured separators.\n * @returns The HL7 MSH-2 field value.\n */\n getMsh2(): string {\n return (\n this.fieldSeparator +\n this.componentSeparator +\n this.repetitionSeparator +\n this.escapeCharacter +\n this.subcomponentSeparator\n );\n }\n}\n\n/**\n * The Hl7Message class represents one HL7 message.\n * A message is a collection of segments.\n */\nexport class Hl7Message {\n readonly context: Hl7Context;\n readonly segments: Hl7Segment[];\n\n /**\n * Creates a new HL7 message.\n * @param segments The HL7 segments.\n * @param context Optional HL7 parsing context.\n */\n constructor(segments: Hl7Segment[], context = new Hl7Context()) {\n this.context = context;\n this.segments = segments;\n }\n\n /**\n * Returns an HL7 segment by index or by name.\n * @param index The HL7 segment index or name.\n * @returns The HL7 segment if found; otherwise, undefined.\n */\n get(index: number | string): Hl7Segment | undefined {\n if (typeof index === 'number') {\n return this.segments[index];\n }\n return this.segments.find((s) => s.name === index);\n }\n\n /**\n * Returns all HL7 segments of a given name.\n * @param name The HL7 segment name.\n * @returns An array of HL7 segments with the specified name.\n */\n getAll(name: string): Hl7Segment[] {\n return this.segments.filter((s) => s.name === name);\n }\n\n /**\n * Returns the HL7 message as a string.\n * @returns The HL7 message as a string.\n */\n toString(): string {\n return this.segments.map((s) => s.toString()).join(this.context.segmentSeparator);\n }\n\n /**\n * Returns an HL7 \"ACK\" (acknowledgement) message for this message.\n * @returns The HL7 \"ACK\" message.\n */\n buildAck(): Hl7Message {\n const now = new Date();\n const msh = this.get('MSH');\n const sendingApp = msh?.get(2)?.toString() || '';\n const sendingFacility = msh?.get(3)?.toString() || '';\n const receivingApp = msh?.get(4)?.toString() || '';\n const receivingFacility = msh?.get(5)?.toString() || '';\n const controlId = msh?.get(9)?.toString() || '';\n const versionId = msh?.get(12)?.toString() || '2.5.1';\n\n return new Hl7Message([\n new Hl7Segment(\n [\n 'MSH',\n this.context.getMsh2(),\n receivingApp,\n receivingFacility,\n sendingApp,\n sendingFacility,\n now.toISOString(),\n '',\n 'ACK',\n now.getTime().toString(),\n 'P',\n versionId,\n ],\n this.context\n ),\n new Hl7Segment(['MSA', 'AA', controlId, 'OK'], this.context),\n ]);\n }\n\n /**\n * Parses an HL7 message string into an Hl7Message object.\n * @param text The HL7 message text.\n * @returns The parsed HL7 message.\n */\n static parse(text: string): Hl7Message {\n if (!text.startsWith('MSH')) {\n const err = new Error('Invalid HL7 message');\n (err as any).type = 'entity.parse.failed';\n throw err;\n }\n const context = new Hl7Context(\n '\\r',\n text.charAt(3), // Field separator, recommended \"|\"\n text.charAt(4), // Component separator, recommended \"^\"\n text.charAt(5), // Repetition separator, recommended \"~\"\n text.charAt(6), // Escape character, recommended \"\\\"\n text.charAt(7) // Subcomponent separator, recommended \"&\"\n );\n return new Hl7Message(\n text.split(/[\\r\\n]+/).map((line) => Hl7Segment.parse(line, context)),\n context\n );\n }\n}\n\n/**\n * The Hl7Segment class represents one HL7 segment.\n * A segment is a collection of fields.\n * The name field is the first field.\n */\nexport class Hl7Segment {\n readonly context: Hl7Context;\n readonly name: string;\n readonly fields: Hl7Field[];\n\n /**\n * Creates a new HL7 segment.\n * @param fields The HL7 fields.\n * @param context Optional HL7 parsing context.\n */\n constructor(fields: Hl7Field[] | string[], context = new Hl7Context()) {\n this.context = context;\n if (isStringArray(fields)) {\n this.fields = fields.map((f) => Hl7Field.parse(f));\n } else {\n this.fields = fields;\n }\n this.name = this.fields[0].components[0][0];\n }\n\n /**\n * Returns an HL7 field by index.\n * @param index The HL7 field index.\n * @returns The HL7 field.\n */\n get(index: number): Hl7Field {\n return this.fields[index];\n }\n\n /**\n * Returns the HL7 segment as a string.\n * @returns The HL7 segment as a string.\n */\n toString(): string {\n return this.fields.map((f) => f.toString()).join(this.context.fieldSeparator);\n }\n\n /**\n * Parses an HL7 segment string into an Hl7Segment object.\n * @param text The HL7 segment text.\n * @param context Optional HL7 parsing context.\n * @returns The parsed HL7 segment.\n */\n static parse(text: string, context = new Hl7Context()): Hl7Segment {\n return new Hl7Segment(\n text.split(context.fieldSeparator).map((f) => Hl7Field.parse(f, context)),\n context\n );\n }\n}\n\n/**\n * The Hl7Field class represents one HL7 field.\n * A field is a collection of components.\n */\nexport class Hl7Field {\n readonly context: Hl7Context;\n readonly components: string[][];\n\n /**\n * Creates a new HL7 field.\n * @param components The HL7 components.\n * @param context Optional HL7 parsing context.\n */\n constructor(components: string[][], context = new Hl7Context()) {\n this.context = context;\n this.components = components;\n }\n\n /**\n * Returns an HL7 component by index.\n * @param component The component index.\n * @param subcomponent Optional subcomponent index.\n * @param repetition Optional repetition index.\n * @returns The string value of the specified component.\n */\n get(component: number, subcomponent?: number, repetition = 0): string {\n let value = this.components[repetition][component] || '';\n\n if (subcomponent !== undefined) {\n value = value.split(this.context.subcomponentSeparator)[subcomponent] || '';\n }\n\n return value;\n }\n\n /**\n * Returns the HL7 field as a string.\n * @returns The HL7 field as a string.\n */\n toString(): string {\n return this.components.map((r) => r.join(this.context.componentSeparator)).join(this.context.repetitionSeparator);\n }\n\n /**\n * Parses an HL7 field string into an Hl7Field object.\n * @param text The HL7 field text.\n * @param context Optional HL7 parsing context.\n * @returns The parsed HL7 field.\n */\n static parse(text: string, context = new Hl7Context()): Hl7Field {\n return new Hl7Field(\n text.split(context.repetitionSeparator).map((r) => r.split(context.componentSeparator)),\n context\n );\n }\n}\n\ninterface Hl7DateParseOptions {\n seconds?: boolean;\n tzOffset?: string;\n}\n\n/**\n * Returns a formatted string representing the date in ISO-8601 format.\n * @param hl7Date Date string.\n * @param options Optional configuration Object\n * @returns The date in ISO-8601 format.\n */\nexport function parseHl7Date(hl7Date: string | undefined, options?: Hl7DateParseOptions): string | undefined {\n if (!hl7Date) {\n return undefined;\n }\n\n options = { ...{ seconds: true, tzOffset: 'Z' }, ...options };\n\n const year = Number.parseInt(hl7Date.substring(0, 4), 10);\n const month = Number.parseInt(hl7Date.substring(4, 6), 10);\n const date = Number.parseInt(hl7Date.substring(6, 8), 10);\n const hours = Number.parseInt(hl7Date.substring(8, 10), 10);\n const minutes = Number.parseInt(hl7Date.substring(10, 12), 10);\n\n const seconds = options.seconds ? Number.parseInt(hl7Date.substring(12, 14), 10) : 0;\n\n return `${pad2(year)}-${pad2(month)}-${pad2(date)}T${pad2(hours)}:${pad2(minutes)}:${pad2(seconds)}.000${\n options.tzOffset\n }`;\n}\n\nfunction pad2(n: number): string {\n return n.toString().padStart(2, '0');\n}\n"],"names":[],"mappings":"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"}