@medplum/core 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -261,6 +261,102 @@
261
261
  }
262
262
  return capitalize(builder.join(' ').trim());
263
263
  }
264
+ /**
265
+ * Returns a human-readable string for a FHIR Range datatype, taking into account comparators and one-sided ranges
266
+ * @param range A FHIR Range element
267
+ * @param exclusive If true, one-sided ranges will be rendered with the '>' or '<' bounds rather than '>=' or '<='
268
+ * @returns A human-readable string representation of the Range
269
+ */
270
+ function formatRange(range, precision, exclusive = false) {
271
+ var _a, _b, _c, _d;
272
+ if (exclusive && precision === undefined) {
273
+ throw new Error('Precision must be specified for exclusive ranges');
274
+ }
275
+ const low = (range === null || range === void 0 ? void 0 : range.low) && Object.assign({}, range.low);
276
+ const high = (range === null || range === void 0 ? void 0 : range.high) && Object.assign({}, range.high);
277
+ if (!range || ((low === null || low === void 0 ? void 0 : low.value) === undefined && (high === null || high === void 0 ? void 0 : high.value) === undefined)) {
278
+ return '';
279
+ }
280
+ if (((_a = range.low) === null || _a === void 0 ? void 0 : _a.value) !== undefined && ((_b = range.high) === null || _b === void 0 ? void 0 : _b.value) === undefined) {
281
+ if (exclusive && precision !== undefined) {
282
+ range.low.value = preciseDecrement(range.low.value, precision);
283
+ return `> ${formatQuantity(range.low, precision)}`;
284
+ }
285
+ return `>= ${formatQuantity(range.low, precision)}`;
286
+ }
287
+ if (((_c = range.low) === null || _c === void 0 ? void 0 : _c.value) === undefined && ((_d = range.high) === null || _d === void 0 ? void 0 : _d.value) !== undefined) {
288
+ if (exclusive && precision !== undefined) {
289
+ range.high.value = preciseIncrement(range.high.value, precision);
290
+ return `< ${formatQuantity(range.high, precision)}`;
291
+ }
292
+ return `<= ${formatQuantity(range.high, precision)}`;
293
+ }
294
+ if ((low === null || low === void 0 ? void 0 : low.unit) === (high === null || high === void 0 ? void 0 : high.unit)) {
295
+ low === null || low === void 0 ? true : delete low.unit;
296
+ }
297
+ return `${formatQuantity(low, precision)} - ${formatQuantity(high, precision)}`;
298
+ }
299
+ /**
300
+ * Returns a human-readable string for a FHIR Quantity datatype, taking into account units and comparators
301
+ * @param quantity A FHIR Quantity element
302
+ * @returns A human-readable string representation of the Quantity
303
+ */
304
+ function formatQuantity(quantity, precision) {
305
+ if (!quantity) {
306
+ return '';
307
+ }
308
+ const result = [];
309
+ if (quantity.comparator) {
310
+ result.push(quantity.comparator);
311
+ result.push(' ');
312
+ }
313
+ if (quantity.value !== undefined) {
314
+ if (precision !== undefined) {
315
+ result.push(quantity.value.toFixed(precision));
316
+ }
317
+ else {
318
+ result.push(quantity.value);
319
+ }
320
+ }
321
+ if (quantity.unit) {
322
+ if (quantity.unit !== '%' && result[result.length - 1] !== ' ') {
323
+ result.push(' ');
324
+ }
325
+ result.push(quantity.unit);
326
+ }
327
+ return result.join('').trim();
328
+ }
329
+ /**
330
+ * Returns the input number increased by the `n` units of the specified precision
331
+ * @param a The input number
332
+ * @param precision The precision in number of digits.
333
+ * @param n (default 1) The number of units to add
334
+ */
335
+ function preciseIncrement(a, precision, n = 1) {
336
+ return (toPreciseInteger$1(a, precision) + n) * Math.pow(10, -precision);
337
+ }
338
+ /**
339
+ * Returns the input number decreased by the `n` units of the specified precision
340
+ * @param a The input number
341
+ * @param precision The precision in number of digits.
342
+ * @param n (default 1) The number of units to subtract
343
+ */
344
+ function preciseDecrement(a, precision, n = 1) {
345
+ return (toPreciseInteger$1(a, precision) - n) * Math.pow(10, -precision);
346
+ }
347
+ /**
348
+ * Returns an integer representation of the number with the given precision.
349
+ * For example, if precision is 2, then 1.2345 will be returned as 123.
350
+ * @param a The number.
351
+ * @param precision Optional precision in number of digits.
352
+ * @returns The integer with the given precision.
353
+ */
354
+ function toPreciseInteger$1(a, precision) {
355
+ if (precision === undefined) {
356
+ return a;
357
+ }
358
+ return Math.round(a * Math.pow(10, precision));
359
+ }
264
360
 
265
361
  /**
266
362
  * Creates a reference resource.
@@ -800,6 +896,15 @@
800
896
  return ((((_a = range.low) === null || _a === void 0 ? void 0 : _a.value) === undefined || preciseGreaterThanOrEquals(value, range.low.value, precision)) &&
801
897
  (((_b = range.high) === null || _b === void 0 ? void 0 : _b.value) === undefined || preciseLessThanOrEquals(value, range.high.value, precision)));
802
898
  }
899
+ /**
900
+ * Returns the input number rounded to the specified number of digits.
901
+ * @param a The input number.
902
+ * @param precision The precision in number of digits.
903
+ * @returns The number rounded to the specified number of digits.
904
+ */
905
+ function preciseRound(a, precision) {
906
+ return parseFloat(a.toFixed(precision));
907
+ }
803
908
  /**
804
909
  * Returns true if the two numbers are equal to the given precision.
805
910
  * @param a The first number.
@@ -6265,9 +6370,8 @@
6265
6370
  // PKCE auth based on:
6266
6371
  // https://aws.amazon.com/blogs/security/how-to-add-authentication-single-page-web-application-with-amazon-cognito-oauth2-implementation/
6267
6372
  var _MedplumClient_instances, _MedplumClient_fetch, _MedplumClient_createPdf, _MedplumClient_storage, _MedplumClient_requestCache, _MedplumClient_cacheTime, _MedplumClient_baseUrl, _MedplumClient_clientId, _MedplumClient_authorizeUrl, _MedplumClient_tokenUrl, _MedplumClient_logoutUrl, _MedplumClient_onUnauthenticated, _MedplumClient_accessToken, _MedplumClient_refreshToken, _MedplumClient_refreshPromise, _MedplumClient_profilePromise, _MedplumClient_profile, _MedplumClient_config, _MedplumClient_addLogin, _MedplumClient_refreshProfile, _MedplumClient_getCacheEntry, _MedplumClient_setCacheEntry, _MedplumClient_request, _MedplumClient_addFetchOptionsDefaults, _MedplumClient_setRequestContentType, _MedplumClient_setRequestBody, _MedplumClient_handleUnauthenticated, _MedplumClient_requestAuthorization, _MedplumClient_refresh, _MedplumClient_fetchTokens, _MedplumClient_verifyTokens, _MedplumClient_setupStorageListener;
6268
- const MEDPLUM_VERSION = "1.0.0-a614a88a";
6373
+ const MEDPLUM_VERSION = "1.0.2-0ed0f55a";
6269
6374
  const DEFAULT_BASE_URL = 'https://api.medplum.com/';
6270
- const DEFAULT_SCOPE = 'launch/patient openid fhirUser offline_access user/*.*';
6271
6375
  const DEFAULT_RESOURCE_CACHE_SIZE = 1000;
6272
6376
  const DEFAULT_CACHE_TIME = 60000; // 60 seconds
6273
6377
  const JSON_CONTENT_TYPE = 'application/json';
@@ -6319,6 +6423,11 @@
6319
6423
  * const bundle = await medplum.search('Patient', 'name=Alice');
6320
6424
  * console.log(bundle.total);
6321
6425
  * ```
6426
+ *
6427
+ * <head>
6428
+ * <meta name="algolia:pageRank" content="100" />
6429
+ * </head>
6430
+
6322
6431
  */
6323
6432
  class MedplumClient extends EventTarget {
6324
6433
  constructor(options) {
@@ -6571,10 +6680,10 @@
6571
6680
  * @returns Promise to the authentication response.
6572
6681
  */
6573
6682
  startLogin(loginRequest) {
6574
- var _a, _b;
6683
+ var _a;
6575
6684
  return __awaiter(this, void 0, void 0, function* () {
6576
6685
  const { codeChallenge, codeChallengeMethod } = this.getCodeChallenge(loginRequest);
6577
- return this.post('auth/login', Object.assign(Object.assign({}, loginRequest), { clientId: (_a = loginRequest.clientId) !== null && _a !== void 0 ? _a : __classPrivateFieldGet(this, _MedplumClient_clientId, "f"), scope: (_b = loginRequest.scope) !== null && _b !== void 0 ? _b : DEFAULT_SCOPE, codeChallengeMethod,
6686
+ return this.post('auth/login', Object.assign(Object.assign({}, loginRequest), { clientId: (_a = loginRequest.clientId) !== null && _a !== void 0 ? _a : __classPrivateFieldGet(this, _MedplumClient_clientId, "f"), scope: loginRequest.scope, codeChallengeMethod,
6578
6687
  codeChallenge }));
6579
6688
  });
6580
6689
  }
@@ -6587,10 +6696,10 @@
6587
6696
  * @returns Promise to the authentication response.
6588
6697
  */
6589
6698
  startGoogleLogin(loginRequest) {
6590
- var _a, _b;
6699
+ var _a;
6591
6700
  return __awaiter(this, void 0, void 0, function* () {
6592
6701
  const { codeChallenge, codeChallengeMethod } = this.getCodeChallenge(loginRequest);
6593
- return this.post('auth/google', Object.assign(Object.assign({}, loginRequest), { clientId: (_a = loginRequest.clientId) !== null && _a !== void 0 ? _a : __classPrivateFieldGet(this, _MedplumClient_clientId, "f"), scope: (_b = loginRequest.scope) !== null && _b !== void 0 ? _b : DEFAULT_SCOPE, codeChallengeMethod,
6702
+ return this.post('auth/google', Object.assign(Object.assign({}, loginRequest), { clientId: (_a = loginRequest.clientId) !== null && _a !== void 0 ? _a : __classPrivateFieldGet(this, _MedplumClient_clientId, "f"), scope: loginRequest.scope, codeChallengeMethod,
6594
6703
  codeChallenge }));
6595
6704
  });
6596
6705
  }
@@ -6994,6 +7103,16 @@
6994
7103
  return this.get(this.fhirUrl(resourceType, id, '_history', vid), options);
6995
7104
  }
6996
7105
  /**
7106
+ * Executes the Patient "everything" operation for a patient.
7107
+ *
7108
+ * Example:
7109
+ *
7110
+ * ```typescript
7111
+ * const bundle = await medplum.readPatientEverything('123');
7112
+ * console.log(bundle);
7113
+ * ```
7114
+ *
7115
+ * See the FHIR "patient-everything" operation for full details: https://hl7.org/fhir/operation-patient-everything.html
6997
7116
  *
6998
7117
  * @category Read
6999
7118
  * @param id The Patient Id
@@ -7724,7 +7843,6 @@
7724
7843
  url.searchParams.set('state', sessionStorage.getItem('pkceState'));
7725
7844
  url.searchParams.set('client_id', __classPrivateFieldGet(this, _MedplumClient_clientId, "f"));
7726
7845
  url.searchParams.set('redirect_uri', getBaseUrl());
7727
- url.searchParams.set('scope', DEFAULT_SCOPE);
7728
7846
  url.searchParams.set('code_challenge_method', 'S256');
7729
7847
  url.searchParams.set('code_challenge', sessionStorage.getItem('codeChallenge'));
7730
7848
  window.location.assign(url.toString());
@@ -10479,30 +10597,83 @@
10479
10597
  return parseFhirPath(expression).eval(input);
10480
10598
  }
10481
10599
 
10482
- const SEGMENT_SEPARATOR = '\r';
10483
- const FIELD_SEPARATOR = '|';
10484
- const COMPONENT_SEPARATOR = '^';
10600
+ /**
10601
+ * The Hl7Context class represents the parsing context for an HL7 message.
10602
+ *
10603
+ * MSH-1:
10604
+ * https://hl7-definition.caristix.com/v2/HL7v2.6/Fields/MSH.1
10605
+ *
10606
+ * MSH-2:
10607
+ * https://hl7-definition.caristix.com/v2/HL7v2.6/Fields/MSH.2
10608
+ *
10609
+ * See this tutorial on MSH, and why it's a bad idea to use anything other than the default values:
10610
+ * https://www.hl7soup.com/HL7TutorialMSH.html
10611
+ */
10612
+ class Hl7Context {
10613
+ constructor(segmentSeparator = '\r', fieldSeparator = '|', componentSeparator = '^', repetitionSeparator = '~', escapeCharacter = '\\', subcomponentSeparator = '&') {
10614
+ this.segmentSeparator = segmentSeparator;
10615
+ this.fieldSeparator = fieldSeparator;
10616
+ this.componentSeparator = componentSeparator;
10617
+ this.repetitionSeparator = repetitionSeparator;
10618
+ this.escapeCharacter = escapeCharacter;
10619
+ this.subcomponentSeparator = subcomponentSeparator;
10620
+ }
10621
+ /**
10622
+ * Returns the MSH-2 field value based on the configured separators.
10623
+ * @returns The HL7 MSH-2 field value.
10624
+ */
10625
+ getMsh2() {
10626
+ return (this.fieldSeparator +
10627
+ this.componentSeparator +
10628
+ this.repetitionSeparator +
10629
+ this.escapeCharacter +
10630
+ this.subcomponentSeparator);
10631
+ }
10632
+ }
10485
10633
  /**
10486
10634
  * The Hl7Message class represents one HL7 message.
10487
10635
  * A message is a collection of segments.
10488
- * Note that we do not strictly parse messages, and only use default delimeters.
10489
10636
  */
10490
10637
  class Hl7Message {
10491
- constructor(segments) {
10638
+ /**
10639
+ * Creates a new HL7 message.
10640
+ * @param segments The HL7 segments.
10641
+ * @param context Optional HL7 parsing context.
10642
+ */
10643
+ constructor(segments, context = new Hl7Context()) {
10644
+ this.context = context;
10492
10645
  this.segments = segments;
10493
10646
  }
10647
+ /**
10648
+ * Returns an HL7 segment by index or by name.
10649
+ * @param index The HL7 segment index or name.
10650
+ * @returns The HL7 segment if found; otherwise, undefined.
10651
+ */
10494
10652
  get(index) {
10495
10653
  if (typeof index === 'number') {
10496
10654
  return this.segments[index];
10497
10655
  }
10498
10656
  return this.segments.find((s) => s.name === index);
10499
10657
  }
10658
+ /**
10659
+ * Returns all HL7 segments of a given name.
10660
+ * @param name The HL7 segment name.
10661
+ * @returns An array of HL7 segments with the specified name.
10662
+ */
10500
10663
  getAll(name) {
10501
10664
  return this.segments.filter((s) => s.name === name);
10502
10665
  }
10666
+ /**
10667
+ * Returns the HL7 message as a string.
10668
+ * @returns The HL7 message as a string.
10669
+ */
10503
10670
  toString() {
10504
- return this.segments.map((s) => s.toString()).join(SEGMENT_SEPARATOR);
10671
+ return this.segments.map((s) => s.toString()).join(this.context.segmentSeparator);
10505
10672
  }
10673
+ /**
10674
+ * Returns an HL7 "ACK" (acknowledgement) message for this message.
10675
+ * @returns The HL7 "ACK" message.
10676
+ */
10506
10677
  buildAck() {
10507
10678
  var _a, _b, _c, _d, _e, _f;
10508
10679
  const now = new Date();
@@ -10516,7 +10687,7 @@
10516
10687
  return new Hl7Message([
10517
10688
  new Hl7Segment([
10518
10689
  'MSH',
10519
- '^~\\&',
10690
+ this.context.getMsh2(),
10520
10691
  receivingApp,
10521
10692
  receivingFacility,
10522
10693
  sendingApp,
@@ -10527,62 +10698,119 @@
10527
10698
  now.getTime().toString(),
10528
10699
  'P',
10529
10700
  versionId,
10530
- ]),
10531
- new Hl7Segment(['MSA', 'AA', controlId, 'OK']),
10701
+ ], this.context),
10702
+ new Hl7Segment(['MSA', 'AA', controlId, 'OK'], this.context),
10532
10703
  ]);
10533
10704
  }
10705
+ /**
10706
+ * Parses an HL7 message string into an Hl7Message object.
10707
+ * @param text The HL7 message text.
10708
+ * @returns The parsed HL7 message.
10709
+ */
10534
10710
  static parse(text) {
10535
- if (!text.startsWith('MSH|^~\\&')) {
10711
+ if (!text.startsWith('MSH')) {
10536
10712
  const err = new Error('Invalid HL7 message');
10537
10713
  err.type = 'entity.parse.failed';
10538
10714
  throw err;
10539
10715
  }
10540
- return new Hl7Message(text.split(/[\r\n]+/).map((line) => Hl7Segment.parse(line)));
10716
+ const context = new Hl7Context('\r', text.charAt(3), // Field separator, recommended "|"
10717
+ text.charAt(4), // Component separator, recommended "^"
10718
+ text.charAt(5), // Repetition separator, recommended "~"
10719
+ text.charAt(6), // Escape character, recommended "\"
10720
+ text.charAt(7) // Subcomponent separator, recommended "&"
10721
+ );
10722
+ return new Hl7Message(text.split(/[\r\n]+/).map((line) => Hl7Segment.parse(line, context)), context);
10541
10723
  }
10542
10724
  }
10543
10725
  /**
10544
10726
  * The Hl7Segment class represents one HL7 segment.
10545
10727
  * A segment is a collection of fields.
10546
10728
  * The name field is the first field.
10547
- * Note that we do not strictly parse messages, and only use default delimeters.
10548
10729
  */
10549
10730
  class Hl7Segment {
10550
- constructor(fields) {
10731
+ /**
10732
+ * Creates a new HL7 segment.
10733
+ * @param fields The HL7 fields.
10734
+ * @param context Optional HL7 parsing context.
10735
+ */
10736
+ constructor(fields, context = new Hl7Context()) {
10737
+ this.context = context;
10551
10738
  if (isStringArray(fields)) {
10552
10739
  this.fields = fields.map((f) => Hl7Field.parse(f));
10553
10740
  }
10554
10741
  else {
10555
10742
  this.fields = fields;
10556
10743
  }
10557
- this.name = this.fields[0].components[0];
10744
+ this.name = this.fields[0].components[0][0];
10558
10745
  }
10746
+ /**
10747
+ * Returns an HL7 field by index.
10748
+ * @param index The HL7 field index.
10749
+ * @returns The HL7 field.
10750
+ */
10559
10751
  get(index) {
10560
10752
  return this.fields[index];
10561
10753
  }
10754
+ /**
10755
+ * Returns the HL7 segment as a string.
10756
+ * @returns The HL7 segment as a string.
10757
+ */
10562
10758
  toString() {
10563
- return this.fields.map((f) => f.toString()).join(FIELD_SEPARATOR);
10759
+ return this.fields.map((f) => f.toString()).join(this.context.fieldSeparator);
10564
10760
  }
10565
- static parse(text) {
10566
- return new Hl7Segment(text.split(FIELD_SEPARATOR).map((f) => Hl7Field.parse(f)));
10761
+ /**
10762
+ * Parses an HL7 segment string into an Hl7Segment object.
10763
+ * @param text The HL7 segment text.
10764
+ * @param context Optional HL7 parsing context.
10765
+ * @returns The parsed HL7 segment.
10766
+ */
10767
+ static parse(text, context = new Hl7Context()) {
10768
+ return new Hl7Segment(text.split(context.fieldSeparator).map((f) => Hl7Field.parse(f, context)), context);
10567
10769
  }
10568
10770
  }
10569
10771
  /**
10570
10772
  * The Hl7Field class represents one HL7 field.
10571
10773
  * A field is a collection of components.
10572
- * Note that we do not strictly parse messages, and only use default delimeters.
10573
10774
  */
10574
10775
  class Hl7Field {
10575
- constructor(components) {
10776
+ /**
10777
+ * Creates a new HL7 field.
10778
+ * @param components The HL7 components.
10779
+ * @param context Optional HL7 parsing context.
10780
+ */
10781
+ constructor(components, context = new Hl7Context()) {
10782
+ this.context = context;
10576
10783
  this.components = components;
10577
10784
  }
10578
- get(index) {
10579
- return this.components[index];
10785
+ /**
10786
+ * Returns an HL7 component by index.
10787
+ * @param component The component index.
10788
+ * @param subcomponent Optional subcomponent index.
10789
+ * @param repetition Optional repetition index.
10790
+ * @returns The string value of the specified component.
10791
+ */
10792
+ get(component, subcomponent, repetition = 0) {
10793
+ let value = this.components[repetition][component] || '';
10794
+ if (subcomponent !== undefined) {
10795
+ value = value.split(this.context.subcomponentSeparator)[subcomponent] || '';
10796
+ }
10797
+ return value;
10580
10798
  }
10799
+ /**
10800
+ * Returns the HL7 field as a string.
10801
+ * @returns The HL7 field as a string.
10802
+ */
10581
10803
  toString() {
10582
- return this.components.join(COMPONENT_SEPARATOR);
10804
+ return this.components.map((r) => r.join(this.context.componentSeparator)).join(this.context.repetitionSeparator);
10583
10805
  }
10584
- static parse(text) {
10585
- return new Hl7Field(text.split(COMPONENT_SEPARATOR));
10806
+ /**
10807
+ * Parses an HL7 field string into an Hl7Field object.
10808
+ * @param text The HL7 field text.
10809
+ * @param context Optional HL7 parsing context.
10810
+ * @returns The parsed HL7 field.
10811
+ */
10812
+ static parse(text, context = new Hl7Context()) {
10813
+ return new Hl7Field(text.split(context.repetitionSeparator).map((r) => r.split(context.componentSeparator)), context);
10586
10814
  }
10587
10815
  }
10588
10816
 
@@ -11306,7 +11534,6 @@
11306
11534
  exports.AndAtom = AndAtom;
11307
11535
  exports.ArithemticOperatorAtom = ArithemticOperatorAtom;
11308
11536
  exports.AsAtom = AsAtom;
11309
- exports.COMPONENT_SEPARATOR = COMPONENT_SEPARATOR;
11310
11537
  exports.ConcatAtom = ConcatAtom;
11311
11538
  exports.ContainsAtom = ContainsAtom;
11312
11539
  exports.DEFAULT_SEARCH_COUNT = DEFAULT_SEARCH_COUNT;
@@ -11316,9 +11543,9 @@
11316
11543
  exports.EquivalentAtom = EquivalentAtom;
11317
11544
  exports.FHIRPATH_KEYWORDS = FHIRPATH_KEYWORDS;
11318
11545
  exports.FHIRPATH_OPERATORS = FHIRPATH_OPERATORS;
11319
- exports.FIELD_SEPARATOR = FIELD_SEPARATOR;
11320
11546
  exports.FhirPathAtom = FhirPathAtom;
11321
11547
  exports.FunctionAtom = FunctionAtom;
11548
+ exports.Hl7Context = Hl7Context;
11322
11549
  exports.Hl7Field = Hl7Field;
11323
11550
  exports.Hl7Message = Hl7Message;
11324
11551
  exports.Hl7Segment = Hl7Segment;
@@ -11334,7 +11561,6 @@
11334
11561
  exports.OperationOutcomeError = OperationOutcomeError;
11335
11562
  exports.OrAtom = OrAtom;
11336
11563
  exports.ReadablePromise = ReadablePromise;
11337
- exports.SEGMENT_SEPARATOR = SEGMENT_SEPARATOR;
11338
11564
  exports.SymbolAtom = SymbolAtom;
11339
11565
  exports.UnaryOperatorAtom = UnaryOperatorAtom;
11340
11566
  exports.UnionAtom = UnionAtom;
@@ -11372,6 +11598,8 @@
11372
11598
  exports.formatGivenName = formatGivenName;
11373
11599
  exports.formatHumanName = formatHumanName;
11374
11600
  exports.formatPeriod = formatPeriod;
11601
+ exports.formatQuantity = formatQuantity;
11602
+ exports.formatRange = formatRange;
11375
11603
  exports.formatSearchQuery = formatSearchQuery;
11376
11604
  exports.formatTime = formatTime;
11377
11605
  exports.formatTiming = formatTiming;
@@ -11422,6 +11650,7 @@
11422
11650
  exports.preciseGreaterThanOrEquals = preciseGreaterThanOrEquals;
11423
11651
  exports.preciseLessThan = preciseLessThan;
11424
11652
  exports.preciseLessThanOrEquals = preciseLessThanOrEquals;
11653
+ exports.preciseRound = preciseRound;
11425
11654
  exports.removeDuplicates = removeDuplicates;
11426
11655
  exports.resolveId = resolveId;
11427
11656
  exports.setCodeBySystem = setCodeBySystem;