8000 RELEASE ENG-268 Updates to GlobalSearch Plumbing / ENG-198 ECW Backend by leite08 · Pull Request #3892 · metriport/metriport · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

RELEASE ENG-268 Updates to GlobalSearch Plumbing / ENG-198 ECW Backend #3892

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 59 commits into from
May 23, 2025

Conversation

leite08
Copy link
Member
@leite08 leite08 commented May 23, 2025

Issues:

Dependencies

Upstream:

Description

Testing

Check each PR.

Release Plan

  • ⚠️ Points to master
  • Upstream dependencies are met
  • Merge this

Summary by CodeRabbit

  • New Features

    • Added support for EClinicalWorks EHR integration, including new API routes, JWT token handling, and patient synchronization.
    • Introduced lexical search functionality for consolidated patient data and enhanced OpenSearch ingestion and search capabilities.
    • Expanded FHIR resource-to-string conversion for AI summarization, supporting more resource types and improved formatting.
    • Added internal endpoints for managing and ingesting consolidated patient data into search indexes.
  • Improvements

    • Refined search and ingestion configuration, error handling, and logging across search and ingestion workflows.
    • Enhanced documentation and debug options for FHIR resource formatting and search results.
  • Bug Fixes

    • Corrected error messages and improved minimum data validation for various FHIR resource conversions.
  • Chores

    • Updated and reorganized import paths, removed deprecated or unused files, and improved environment variable management.
  • Tests

    • Added comprehensive unit tests for FHIR codeable concept and timing formatting utilities.

husainsyed and others added 30 commits May 16, 2025 12:55
refs. metriport/metriport-internal#198

Signed-off-by: Syed Husain <syed@metriport.com>
Ref: ENG-198

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-199

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-199

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
refs. metriport/metriport-internal#198

Signed-off-by: Syed Husain <syed@metriport.com>
Ref: ENG-198

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
…triport into 198-ecw-patientflow

Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
… 198-ecw-v2

Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref eng-41

Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
- group OS bulk errors to Sentry
- store individual errors in NDJON when run from utils

Ref eng-41

Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268

Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268

Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268

Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268

Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
- move getConsolidated to core
- reorg OS code on core

Ref eng-268

Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268

Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268

Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268

Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268

Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268

Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
leite08 and others added 5 commits May 23, 2025 18:15
Ref eng-268

Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref: ENG-198

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref eng-268

Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
@thomasyopes thomasyopes changed the title RELEASE ENG-268 Updates to GlobalSearch Plumbing RELEASE ENG-268 Updates to GlobalSearch Plumbing / ENG-198 ECW Backend May 23, 2025
Copy link
linear bot commented May 23, 2025

@leite08 leite08 added this pull request to the merge queue May 23, 2025
Merged via the queue into master with commit d854264 May 23, 2025
80 of 81 checks passed
Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 40

🔭 Outside diff range comments (3)
packages/core/src/external/opensearch/file/file-remover-direct.ts (1)

21-21: 🛠️ Refactor suggestion

Consider adding error handling for the delete operation.

The OpenSearch delete operation could fail and should be wrapped in a try/catch block to provide better error handling and logging.

  async remove(entryId: string): Promise<void> {
    const { indexName, endpoint, username, password } = this.config;
    const { log } = out(`OSFileRemover.remove - entryId ${entryId}`);

    const auth = { username, password };
    const client = new Client({ node: endpoint, auth });

-   await client.delete({ index: indexName, id: entryId });
-   log(`Successfully deleted ${entryId}`);
+   try {
+     await client.delete({ index: indexName, id: entryId });
+     log(`Successfully deleted ${entryId}`);
+   } catch (error) {
+     const errorMsg = `Failed to delete entry ${entryId} from OpenSearch`;
+     log(errorMsg);
+     throw new Error(errorMsg, { cause: error });
+   }
  }
packages/core/src/external/opensearch/semantic/semantic-searcher.ts (1)

20-24: 💡 Verification agent

🧩 Analysis chain

Mismatch between JSDoc and runtime validation makes 0 an impossible but documented value

The JSDoc states that both maxNumberOfResults and similarityThreshold accept a lower bound of 0, yet the validators throw for maxNumberOfResults < 1 and similarityThreshold <= 0.
This silent contract breach will surface only at runtime and is hard to diagnose.

-  /** From 0 to 10_000, optional, defaults to 100 */
+  /** From 1 to 10_000, optional, defaults to 100 */
...
-  /** From 0 to 1, optional, defaults to 0.2 */
+  /** From (0, 1], optional, defaults to 0.2 */

or loosen the guards, e.g.

- if (maxNumberOfResults < 1) {
-   throw new BadRequestError("maxNumberOfResults cannot be less than 1");
- }
+ if (maxNumberOfResults < 0) {
+   throw new BadRequestError("maxNumberOfResults cannot be negative");
+ }

Align the two sides before this ships.

Also applies to: 78-85, 87-94


🏁 Script executed:

#!/bin/bash
set -e
# Show declarations and runtime checks for maxNumberOfResults
rg -n "maxNumberOfResults" -C3 packages/core/src/external/opensearch/semantic/semantic-searcher.ts

# Show declarations and runtime checks for similarityThreshold
rg -n "similarityThreshold" -C3 packages/core/src/external/opensearch/semantic/semantic-searcher.ts

Length of output: 3339


Align JSDoc bounds with runtime validation

The JSDoc for both parameters currently documents a lower bound of 0, but the actual validators enforce:

  • maxNumberOfResults ≥ 1
  • similarityThreshold ∈ (0, 1]

This mismatch means setting either to 0 (as the docs allow) will throw at runtime.

Locations to fix:

  • packages/core/src/external/opensearch/semantic/semantic-searcher.ts, lines 20–24 (JSDoc for the two fields)

Suggested diff:

-  /** From 0 to 10_000, optional, defaults to 100 */
+  /** From 1 to 10_000, optional, defaults to 100 */
   maxNumberOfResults?: number | undefined;
-  /** From 0 to 1, optional, defaults to 0.2 */
+  /** From (0, 1], optional, defaults to 0.2 */
   similarityThreshold?: number | undefined;

Alternatively, if you prefer to allow 0, adjust the guards in validateMaxNumberOfResults and validateSimilarityThreshold to match the documented bounds.

packages/core/src/command/ai-brief/filter.ts (1)

409-415: ⚠️ Potential issue

Case-sensitive filter may leak stale lab reports

nonLabReports omits a toLowerCase() call, so any category value like “Laboratory Data” will slip through, defeating the whole purpose of the filter and potentially bloating the AI payload.

-  const nonLabReports = reports.filter(report => !report.category?.includes("laboratory data"));
+  const nonLabReports = reports.filter(
+    report =>
+      !(
+        report.category &&
+        typeof report.category === "string" &&
+        report.category.toLowerCase().includes("laboratory data")
+      )
+  );
🧹 Nitpick comments (64)
packages/core/src/external/html/remove-tags.ts (2)

52-52: Use optional chaining for cleaner code.

As suggested by the static analysis tool, you can simplify the conditional logging using optional chaining.

- log && log(`Removing HTML tags...`);
+ log?.(`Removing HTML tags...`);
🧰 Tools
🪛 Biome (1.9.4)

[error] 52-52: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


18-32: Consider extracting regex patterns to constants.

For better maintainability and reusability, consider extracting the com 6D47 piled regex patterns to module-level constants with descriptive names.

+ // Module-level regex constants for better reusability
+ const REGEX_GENERIC_WORDS = new RegExp(
+   `(${genericStopWords.map(w => w.toLowerCase()).join("|")})`,
+   "g"
+ );
+ const REGEX_HTML_TAGS = new RegExp(
+   `</?(${htmlStopWords.map(w => w.toLowerCase()).join("|")})(\\s.*?)?/?>`,
+   "g"
+ );
+ const REGEX_FORMATTING = /(__+|--+)/g;
+ const REGEX_MARKUP_ATTRIBUTES = /((\w+(:\w+)?)(:\w+)?="(?<content>[^"]+?)")/g;
+ const REGEX_ADDITIONAL_MARKUP = /<(\w+(:\w+)?)(\s*|\s(?<content>[^>]+?))\/?>/g;
+ const REGEX_CLOSING_MARKUP = /<\/(\w+(:\w+)?)>/g;
+ const REGEX_NEWLINES_TABS = /"|(\n\n)|\n|\t|\r|<!/g;
+ const REGEX_MULTIPLE_SPACES = /(\s\s+)/g;

- const regexGenericWords = new RegExp(
-   `(${genericStopWords.map(w => w.toLowerCase()).join("|")})`,
-   "g"
- );
- // removes the tag w/ attributes, but without content
- const regexHtml = new RegExp(
-   `</?(${htmlStopWords.map(w => w.toLowerCase()).join("|")})(\\s.*?)?/?>`,
-   "g"
- );
- const regexFormatting = new RegExp(/(__+|--+)/g);
- const regexMarkupAttributes = new RegExp(/((\w+(:\w+)?)(:\w+)?="(?<content>[^"]+?)")/g);
- const regexAdditionalMarkup = new RegExp(/<(\w+(:\w+)?)(\s*|\s(?<content>[^>]+?))\/?>/g);
- const regexClosingMarkup = new RegExp(/<\/(\w+(:\w+)?)>/g);
- const regexNewlinesTabs = new RegExp(/"|(\n\n)|\n|\t|\r|<!/g);
- const regexMultipleSpaces = new RegExp(/(\s\s+)/g);
packages/core/src/external/fhir/normalization/resources/encounter.ts (1)

83-85: Good technical debt tracking with TODO comment.

The TODO comment appropriately identifies potential code duplication that should be investigated. This is excellent practice for maintaining code quality.

I can help investigate whether isUsefulDisplay() can replace isDisplayUseful(). Would you like me to search the codebase for similar functions and analyze their compatibility?

#!/bin/bash
# Search for similar display utility functions
ast-grep --pattern 'function isUsefulDisplay($$$) { $$$ }'
ast-grep --pattern 'function isDisplayUseful($$$) { $$$ }'
rg -A 5 "isUsefulDisplay|isDisplayUseful"
packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-factory.ts (1)

4-11: Address the TODO comment for dynamic implementation selection.

The factory function is well-implemented using appropriate patterns, but the TODO comment (ENG-268) indicates incomplete work. Consider whether this should be completed before merging or if there's a plan to address it in a follow-up.

The commented code shows the intended design for environment-based selection between SearchConsolidatedDirect and SearchConsolidatedLambda implementations.

Would you like me to help implement the dynamic selection based on environment configuration, or is this intentionally deferred to a future task?

packages/utils/src/shared/sentry.ts (2)

15-23: Consider making the Sentry configuration more flexible.

The current implementation hardcodes the sample rates, which reduces flexibility for different development scenarios. Consider accepting configuration parameters to make this more reusable.

Apply this diff to make the function more configurable:

-export function initSentry() {
+export function initSentry({
+  sampleRate = 1.0,
+  tracesSampleRate = 0,
+}: {
+  sampleRate?: number;
+  tracesSampleRate?: number;
+} = {}) {
   Sentry.init({
     dsn: sentryDsn,
     enabled: sentryDsn != null,
     environment: getEnvType(),
-    sampleRate: 1.0, // error sample rate
-    tracesSampleRate: 0, // transaction sample rate
+    sampleRate, // error sample rate
+    tracesSampleRate, // transaction sample rate
   });
 }

7-14: Consider programmatic enforcement of development-only usage.

The comment warns against pushing code that enables Sentry in scripts, but this could be enforced programmatically to prevent accidents.

Consider adding a runtime check:

 /**
  * Function to initialize Sentry for rare cases we want to test sending events to Sentry.
  *
  * Note: this should only be called while developing, don't push code to the repo enabling
  * Sentry in scripts that might send lots of messages to Sentry.
  *
  * @see packages/api/src/sentry.ts
  * @see packages/lambdas/src/shared/capture.ts
  */
 export function initSentry() {
+  if (getEnvType() === "production") {
+    throw new Error("initSentry should not be called in production environment");
+  }
   Sentry.init({
packages/core/src/external/opensearch/semantic/hybrid-create.ts (1)

1-1: Address the TODO comment for index creation implementation.

This file currently contains only a commented JSON template. The TODO indicates this needs to be converted to executable code for creating the hybrid search index.

Would you like me to help implement the index creation code or open a new issue to track this task? The JSON template looks well-structured for a hybrid search index with k-NN vector capabilities.

packages/api/src/routes/ehr/eclinicalworks/patient.ts (1)

35-35: Improve response structure consistency.

The response returns a bare patientId value. Consider wrapping it in an object for better API consistency and future extensibility.

-return res.status(httpStatus.OK).json(patientId);
+return res.status(httpStatus.OK).json({ patientId });

Also applies to: 63-63

packages/api/src/routes/ehr/eclinicalworks/routes/dash.ts (1)

17-17: Consider using a more descriptive variable name.

The variable documentSkipPathsForEclinicalworksIdCheck could be shortened to improve readability while maintaining clarity.

-const documentSkipPathsForEclinicalworksIdCheck = [documentDownloadUrlRegex];
+const skipPatientIdCheckPaths = [documentDownloadUrlRegex];

Then update the usage on line 34:

- documentSkipPathsForEclinicalworksIdCheck
+ skipPatientIdCheckPaths
packages/api/src/external/ehr/eclinicalworks/shared.ts (1)

26-35: Consider error handling for client creation.

The createEClinicalWorksClient function looks clean, but consider adding error handling around the EClinicalWorksApi.create() call to provide more context if client creation fails.

 export async function createEClinicalWorksClient(
   perPracticeParams: EClinicalWorksPerPracticeParams
 ): Promise<EClinicalWorksApi> {
   const { environment } = getEClinicalWorksEnv();
-  return await EClinicalWorksApi.create({
-    practiceId: perPracticeParams.practiceId,
-    environment,
-    authToken: perPracticeParams.authToken,
-  });
+  try {
+    return await EClinicalWorksApi.create({
+      practiceId: perPracticeParams.practiceId,
+      environment,
+      authToken: perPracticeParams.authToken,
+    });
+  } catch (error) {
+    throw new MetriportError("Failed to create EClinicalWorks client", error, {
+      practiceId: perPracticeParams.practiceId,
+      environment,
+    });
+  }
packages/core/src/external/fhir/export/string/shared/narrative.ts (1)

5-5: Consider using a more robust HTML filtering approach.

The current array-based filtering approach has potential issues:

  1. The regex construction could be inefficient for larger arrays
  2. It doesn't handle case variations or attributes in div tags
  3. The regex is recreated on every function call

Consider these improvements:

-const filterFromDiv = ['<div xmlns="http://www.w3.org/1999/xhtml">', "<div>", "</div>", "<div/>"];
+const DIV_TAG_REGEX = /<\/?div[^>]*>/gi;

Then in the function:

-const filteredDiv = narrative.div?.replace(new RegExp(filterFromDiv.join("|"), "g"), "");
+const filteredDiv = narrative.div?.replace(DIV_TAG_REGEX, "");
packages/core/src/external/fhir/export/string/shared/deny.ts (1)

17-20: Consider adding TODO comment for stub function.

The isAllowedSystem function is currently a stub that always returns true. This could be problematic if used in production without proper implementation.

Consider adding a TODO comment to make the stub nature explicit:

+// TODO: Implement proper system filtering logic
 // eslint-disable-next-line @typescript-eslint/no-unused-vars
 export function isAllowedSystem(value: string | undefined): boolean {
   return true;
 }
packages/core/src/external/fhir/export/string/resources/coverage.ts (2)

107-118: Apply optional chaining for cleaner code.

The static analysis tool correctly identifies that the nested property access can be simplified using optional chaining.

Apply this diff to improve readability:

-          exception &&
-            exception
-              .map(ex => {
+          exception
+            ?.map(ex => {
                const exComponents = [
                  formatCodeableConcept({ concept: ex.type, label: "Type", isDebug }),
                  formatPeriod({ period: ex.period, label: "Period", isDebug }),
                ].filter(Boolean);
                const exStr = exComponents.join(FIELD_SEPARATOR);
                return exStr.length > 0 ? (isDebug ? `Exception: ${exStr}` : exStr) : undefined;
              })
-              .filter(Boolean)
-              .join(FIELD_SEPARATOR),
+              ?.filter(Boolean)
+              ?.join(FIELD_SEPARATOR),
🧰 Tools
🪛 Biome (1.9.4)

[error] 107-118: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


56-59: Consider uncommenting useful fields or removing commented code.

Several potentially useful fields are commented out (subscriberId, order, network, subrogation). Consider either implementing these fields if they provide value for coverage representation, or removing the commented code to keep the codebase clean.

packages/core/src/external/fhir/resources/diagnostic-report.ts (1)

17-20: Consider tracking the TODO for content type handling.

The TODO comment identifies important future enhancements for handling different content types and downloading external attachments. Consider creating a backlog item to track this enhancement.

Would you like me to create an issue to track the TODO for content type-based conversion and external attachment handling?

packages/core/src/external/fhir/export/string/resources/encounter.ts (1)

13-48: Good refactoring with one consistency suggestion.

The EncounterToString updates follow the established patterns well:

  • Proper isDebug parameter support
  • Good use of emptyIfDenied for status filtering
  • Appropriate hasMinimumData pattern to return undefined when no meaningful data
  • Clean object-based parameter passing to formatting functions

Consider using the formatPeriod utility function for the period formatting (lines 40-44) to maintain consistency with other formatters:

-    if (encounter.period) {
-      const start = encounter.period.start ?? "unknown";
-      const end = encounter.period.end ?? "ongoing";
-      parts.push(isDebug ? `Period: ${start} to ${end}` : `${start} to ${end}`);
-    }
+    const periodStr = formatPeriod({ period: encounter.period, label: "Period", isDebug });
+    if (periodStr) parts.push(periodStr);

This would align with the shared formatting approach used throughout the codebase.

packages/utils/src/fhir/ai-brief/build-slim-bundle.ts (1)

18-20: Fix typo in JSDoc comment.

There's a typo in the comment.

-/**
- * Script compare the output of the buildSlimmerPayload funcion with the original bundle.
- */
+/**
+ * Script to compare the output of the buildSlimmerPayload function with the original bundle.
+ */
packages/core/src/external/fhir/export/string/resources/communication.ts (2)

35-38: Consider documenting the commented subject field.

The commented-out subject field handling suggests planned functionality. Consider adding a TODO comment explaining why it's commented out or when it might be enabled.

-    // if (communication.subject) {
-    //   const subjectStr = formatReferences([communication.subject], "Subject");
-    //   if (subjectStr) parts.push(subjectStr);
-    // }
+    // TODO: Subject field handling - determine if needed for Communication string representation
+    // if (communication.subject) {
+    //   const subjectStr = formatReferences([communication.subject], "Subject");
+    //   if (subjectStr) parts.push(subjectStr);
+    // }

94-111: Complex payload processing looks correct but could benefit from helper function.

The payload processing logic correctly handles multiple content types, but the nested structure makes it somewhat complex to follow. Consider extracting the payload formatting logic into a separate helper function for better readability.

Example refactor:

private formatPayloadContent(payload: CommunicationPayload, isDebug?: boolean): string | undefined {
  const { contentString, contentAttachment, contentReference } = payload;
  const components = [
    contentString && (isDebug ? `Content: ${contentString}` : contentString),
    formatAttachment({ attachment: contentAttachment, isDebug }),
    formatReference({ reference: contentReference, label: "Content Ref", isDebug }),
  ].filter(Boolean);
  return components.length > 0 ? components.join(FIELD_SEPARATOR) : undefined;
}
packages/core/src/external/opensearch/lexical/lexical-search.ts (1)

15-15: Fix regex construction to use literal notation.

Use a regex literal instead of the RegExp constructor for better readability and static analysis.

-  const actualQuery = query.replace(new RegExp(`^\\$\\s*`, "g"), "");
+  const actualQuery = query.replace(/^\$\s*/g, "");
🧰 Tools
🪛 Biome (1.9.4)

[error] 15-15: Use a regular expression literal instead of the RegExp constructor.

Regular expression literals avoid some escaping required in a string literal, and are easier to analyze statically.
Safe fix: Use a literal notation instead.

(lint/complexity/useRegexLiterals)

packages/core/src/external/fhir/export/string/shared/duration.ts (1)

19-19: Use strict equality operator.

The coding guidelines specify using strict equality operator === instead of abstract equality ==. If you need to check for both null and undefined, consider using != null to be more explicit about the intent.

-  if (value != undefined) parts.push(value.toString());
+  if (value !== undefined) parts.push(value.toString());

Or if checking for both null and undefined is intended:

-  if (value != undefined) parts.push(value.toString());
+  if (value != null) parts.push(value.toString());
packages/core/src/external/fhir/export/string/shared/__tests__/codeable-concept.test.ts (1)

15-21: Test logic needs correction.

The test expects undefined for an empty concept, but the test creates a concept with an empty coding array, which may not be the same as a truly empty concept.

Consider testing both scenarios explicitly:

-    it("returns empty string if no concept", () => {
-      const concept: CodeableConcept = { coding: [] };
-      const res = formatCodeableConcept({ concept });
-      expect(res).toBeUndefined();
-    });
+    it("returns undefined if no concept", () => {
+      const res = formatCodeableConcept({ concept: undefined });
+      expect(res).toBeUndefined();
+    });
+
+    it("returns undefined if concept has empty coding array", () => {
+      const concept: CodeableConcept = { coding: [] };
+      const res = formatCodeableConcept({ concept });
+      expect(res).toBeUndefined();
+    });
packages/core/src/external/fhir/export/string/resources/related-person.ts (2)

23-26: Consider removing commented code or documenting the plan.

The commented-out patient reference code should either be removed if not needed or documented with a TODO explaining when it will be implemented.

-    // if (person.patient) {
-    //   const patientStr = formatReferences([person.patient], "Patient");
-    //   if (patientStr) parts.push(patientStr);
-    // }
+    // TODO: Add patient reference formatting when cross-references are supported

54-86: Extensive commented code should be addressed.

Large blocks of commented code for photo and communication handling should either be implemented, removed, or moved to a TODO with clear implementation plans.

Consider creating separate issues for these features:

-    // if (person.photo) {
-    //   const photos = person.photo
-    //     .map(photo => {
-    //       const contentType = photo.contentType ? `Content Type: ${photo.contentType}` : undefined;
-    //       const url = photo.url ? `URL: ${photo.url}` : undefined;
-    //       const size = photo.size ? `Size: ${photo.size}` : undefined;
-    //       const hash = photo.hash ? `Hash: ${photo.hash}` : undefined;
-    //       return [contentType, url, size, hash].filter(Boolean).join(FIELD_SEPARATOR);
-    //     })
-    //     .filter(Boolean);
-
-    //   if (photos.length > 0) {
-    //     parts.push(`Photos: ${photos.join(FIELD_SEPARATOR)}`);
-    //     hasMinimumData = true;
-    //   }
-    // }
-
-    // if (person.communication) {
-    //   const communications = person.communication
-    //     .map(comm => {
-    //       const language = comm.language
-    //         ? formatCodeableConcepts([comm.language], "Language")
-    //         : undefined;
-    //       const preferred = comm.preferred ? `Preferred: ${comm.preferred}` : undefined;
-    //       return [language, preferred].filter(Boolean).join(FIELD_SEPARATOR);
-    //     })
-    //     .filter(Boolean);
-
-    //   if (communications.length > 0) {
-    //     parts.push(`Communications: ${communications.join(FIELD_SEPARATOR)}`);
-    //     hasMinimumData = true;
-    //   }
-    // }
+    // TODO: Implement photo formatting (issue #XXX)
+    // TODO: Implement communication formatting (issue #XXX)
packages/core/src/external/fhir/export/string/resources/medication-administration.ts (1)

58-61: Consider removing or documenting commented subject reference code.

Similar to the RelatedPerson file, commented code should be addressed with clear documentation or removal.

-    // if (administration.subject) {
-    //   const subjectStr = formatReferences([administration.subject], "Subject");
-    //   if (subjectStr) parts.push(subjectStr);
-    // }
+    // TODO: Add subject reference when cross-references are supported
packages/core/src/external/fhir/export/string/resources/medication-dispense.ts (1)

49-54: Clean up commented-out code blocks.

There are commented-out blocks for subject and daysSupply fields. Consider either implementing these fields or removing the commented code to improve maintainability.

-    // if (dispense.subject) {
-    //   const subjectStr = formatReferences({ references: [dispense.subject], label: "Subject", isDebug });
-    //   if (subjectStr) {
-    //     parts.push(subjectStr);
-    //   }
-    // }

-    // if (dispense.daysSupply) {
-    //   const daysSupplyStr = formatQuantity({ quantity: dispense.daysSupply, label: "Days Supply", isDebug });
-    //   if (daysSupplyStr) {
-    //     parts.push(daysSupplyStr);
-    //   }
-    // }

Also applies to: 101-106

packages/core/src/command/consolidated/search/fhir-resource/ingest-lexical.ts (2)

30-38: Unused Promise result – clarify intent or drop it

Promise.all returns an array with two results, but the delete promise is ignored after destructuring.
If the intention is merely to fire-and-forget the delete, consider:

  1. Awaiting it first to guarantee the cleanup happened before ingestion, or
  2. Dropping it from Promise.all and triggering it without awaiting (with proper error handling) to make that intent explicit.
-  const [convertedResources] = await Promise.all([
-    getConsolidatedAsText({ patient }),
-    ingestor.delete({ cxId: patient.cxId, patientId: patient.id }),
-  ]);
+  await ingestor.delete({ cxId: patient.cxId, patientId: patient.id });
+  const convertedResources = await getConsolidatedAsText({ patient });

This also avoids allocating an unnecessary array.


63-71: Config helper duplication – consider single responsibility

getConfigs() is re-implemented in multiple OpenSearch‐related modules. Extracting it into a shared util (e.g., searchConfig.ts) would:

• Remove duplication
• Ensure changes (e.g., env var renames) are propagated automatically
• Improve testability

Not urgent, but advisable before additional search components appear.

packages/core/src/external/fhir/export/string/resources/medication.ts (1)

63-81: Ingredient reference ignored – possible data loss

You removed the itemReference branch (commented out). Some Medication resources populate ingredient.itemReference instead of itemCodeableConcept.
Consider falling back to the reference when the codeable concept is absent to avoid silently omitting ingredients.

-        const item = formatCodeableConcept({
-          concept: ingredient.itemCodeableConcept,
-          label: "Ingredient",
-          isDebug,
-        });
+        const item =
+          formatCodeableConcept({
+            concept: ingredient.itemCodeableConcept,
+            label: "Ingredient",
+            isDebug,
+          }) ??
+          formatReferences({
+            references: [ingredient.itemReference],
+            label: "Ingredient",
+            isDebug,
+          });
packages/core/src/external/fhir/export/string/resources/family-member-history.ts (3)

20-23: Consider surfacing status only when meaningful
history.status is pushed unchanged, which may emit low–information codes like "entered-in-error" to end-users. Usually status is helpful only for debugging; for consumer-facing strings you may want to:

  1. Skip neutral values ("completed", "unknown") or
  2. Localise / prettify them (e.g. "active""Active").
    If the intention is a user-visible sentence rather than raw debug, consider mapping the enum to human-readable text or hide it behind isDebug.

50-53: Avoid wrapping undefined inside arrays
formatCodeableConcepts({ concepts: [history.sex], … }) still creates an array with one element when history.sex is undefined, causing formatCodeableConcepts to iterate once and allocate unnecessarily.
A small guard avoids this overhead and reduces the risk of false “array has length” checks:

-if (history.sex) {
-  const sexStr = formatCodeableConcepts({ concepts: [history.sex], label: "Sex", isDebug });
+if (history.sex) {
+  const sexStr = formatCodeableConcepts({ concepts: [history.sex], label: "Sex", isDebug });

Or:

const sexStr = formatCodeableConcepts({
  concepts: history.sex ? [history.sex] : undefined,
  label: "Sex",
  isDebug,
});

73-75: Ambiguous deceased flag
When history.deceasedBoolean is true the literal string "Deceased" is appended, but in debug mode there is no label/context.
Consider outputting "Deceased: true" (or "Deceased" only when isDebug is off) to keep the pattern consistent with the other labelled fields.

packages/core/src/external/fhir/export/string/shared/timing.ts (3)

24-25: Parentheses precedence makes intent slightly opaque
const eventsWithLabel = eventsStr && isDebug ? … relies on && binding tighter than ?:.
Although correct, a reader may need to double-take. An explicit ternary reads clearer:

const eventsWithLabel = eventsStr
  ? isDebug
    ? `Events: ${eventsStr}`
    : eventsStr
  : undefined;

37-45: formatTimingRepeat is a pure formatter – mark it const and move outside?
The helper closes over no mutable state and is not part of the public API.
Extracting it to its own module or marking it const formatTimingRepeat = (…) => { … } makes the intent (pure, reusable) explicit and avoids hoisting surprises.


112-113: Unit hard-coded as string
formatNumeric({ value: offset, unit: "minutes", … }) duplicates the literal "minutes".
Consider exporting a TIME_UNITS enum / const to avoid typos and enable future localisation.

packages/core/src/external/opensearch/file/file-ingestor-direct.ts (2)

18-20: Left-over regex constants are now unused
regexQuotesNewlinesTabs and regexMultipleSpaces were kept after refactor but are no longer referenced.
Remove them (and their related tests) to avoid dead code and maintainers wondering “why are these here?”.


154-168: makeSureIndexExists leaks as public API
The method was downgraded from private to public but is still an internal helper; exposing it broadens the public surface unnecessarily.
If external access isn’t required, restore private or at least protected visibility.

packages/core/src/external/fhir/export/string/bundle-to-string.ts (1)

78-79: Remove the TODO comment for Patient resource.

The TODO comment suggests Patient should be removed, but Patient is actually included in the bundle construction logic (line 113 in the map). This comment might be outdated or misleading.

  RelatedPerson: RelatedPerson;
- // TODO REMOVE THIS
  Patient: Patient;
packages/core/src/external/fhir/export/string/resources/consent.ts (2)

40-43: Consider removing or implementing commented patient reference code.

The commented code for patient reference formatting should either be implemented if needed or removed if not required. Leaving commented code can create confusion about intended functionality.

If patient reference is needed:

if (consent.patient) {
  const patientStr = formatReference({
    reference: consent.patient,
    label: "Patient",
    isDebug,
  });
  if (patientStr) parts.push(patientStr);
}

Otherwise, remove the commented block.


189-204: Remove commented sub-provision code or implement it.

The extensive commented code for sub-provisions suggests this was either planned functionality or removed code. Consider either implementing it properly with the new formatting patterns or removing it entirely.

If sub-provisions are needed, they should use the current formatting patterns:

if (provision.provision) {
  const subProvisions = provision.provision
    .map(subProvision => {
      const components = [
        subProvision.type && (isDebug ? `Type: ${subProvision.type}` : subProvision.type),
        formatPeriod({ period: subProvision.period, label: "Period", isDebug }),
        formatCodeableConcepts({ concepts: subProvision.code, label: "Code", isDebug }),
      ].filter(Boolean);
      return components.join(FIELD_SEPARATOR);
    })
    .filter(Boolean);

  if (subProvisions.length > 0) {
    const subProvisionsStr = subProvisions.join(FIELD_SEPARATOR);
    provisionParts.push(isDebug ? `Sub-provisions: ${subProvisionsStr}` : subProvisionsStr);
  }
}
packages/core/src/external/fhir/export/string/resources/composition.ts (2)

42-45: Consider removing or documenting commented code.

The commented-out subject field processing should either be removed if no longer needed or documented with a reason for being commented out.

-    // if (composition.subject) {
-    //   const subjectStr = formatReferences([composition.subject], "Subject");
-    //   if (subjectStr) parts.push(subjectStr);
-    // }

If this code will be needed later, consider adding a TODO comment explaining why it's temporarily disabled.


99-101: Remove commented code or document its purpose.

Similar to the subject field, this commented confidentiality code should be cleaned up.

-    // if (composition.confidentiality) {
-    //   parts.push(`Confidentiality: ${composition.confidentiality}`);
-    // }
packages/core/src/external/fhir/export/string/resources/procedure.ts (1)

29-34: Consider cleaning up commented subject processing.

The commented subject field processing should be removed if not needed or documented with a TODO if it will be implemented later.

-    // if (procedure.subject) {
-    //   const subjectStr = formatReferences([procedure.subject], "Subject");
-    //   if (subjectStr) {
-    //     parts.push(subjectStr);
-    //   }
-    // }
packages/core/src/external/fhir/export/string/shared/annotation.ts (2)

35-37: Add parentheses to avoid precedence ambiguities

&& has higher precedence than the ternary ?:, so the current expression is technically correct, but the intent is not immediately obvious at a glance. Wrapping the && clause with parentheses makes the condition explicit and improves readability.

-    authorString && isDebug ? `Author: ${authorString}` : authorString,
+    (authorString && isDebug) ? `Author: ${authorString}` : authorString,

15-18: Consider forwarding label into the per-annotation formatter

formatAnnotations forwards only annotation and isDebug to formatAnnotation.
If the caller supplies a label, each inner annotation will never see it, so per-annotation output can’t be labelled in debug mode. If the desired behaviour is to prefix each annotation with the same label (e.g., “Note 1: …, Note 2: …”), forward the label—or an auto-generated label—downstream.

-    .map(annotation => formatAnnotation({ annotation, isDebug }))
+    .map(annotation => formatAnnotation({ annotation, label, isDebug }))
packages/core/src/external/opensearch/semantic/semantic-searcher.ts (1)

42-45: Instantiate the OpenSearch client once, not per search

Creating a new Client for every search() call incurs TLS handshake & connection-pool overhead and prevents connection reuse. Consider:

-class OpenSearchSemanticSearcher {
-  constructor(readonly config: OpenSearchSemanticSearcherConfig) {}
+class OpenSearchSemanticSearcher {
+  private readonly client: Client;
+  constructor(readonly config: OpenSearchSemanticSearcherConfig) {
+    this.client = new Client({
+      node: config.endpoint,
+      auth: { username: config.username, password: config.password },
+    });
+  }

…and drop the per-call instantiation.

packages/core/src/external/fhir/export/string/shared/human-name.ts (1)

25-27: lodash/uniq is overkill here—dedupe with a Set

uniq adds ~24 kB (min) to the bundle. A single-liner with Set is faster and tree-shakable:

-const dedupedNames = uniq(formattedNames);
+const dedupedNames = [...new Set(formattedNames)];

Same behaviour, lighter footprint.

packages/core/src/external/fhir/export/string/shared/telecom.ts (1)

43-44: Address commented-out code.

The commented lines for use and rank fields should either be implemented or removed. Leaving commented code reduces maintainability and can cause confusion.

Consider either:

  1. Implementing the missing fields if they're needed:
-    // use && isDebug ? `Use: ${use}` : use,
-    // rank && isDebug ? `Rank: ${rank}` : rank,
+    telecom.use && isDebug ? `Use: ${telecom.use}` : telecom.use,
+    telecom.rank && isDebug ? `Rank: ${telecom.rank}` : telecom.rank,
  1. Or removing them entirely if they're not needed:
-    // use && isDebug ? `Use: ${use}` : use,
-    // rank && isDebug ? `Rank: ${rank}` : rank,
packages/api/src/routes/ehr/eclinicalworks/auth/middleware.ts (1)

12-12: Consider making the query parameter constant more descriptive.

The constant name tokenEhrPatientIdQueryParam could be more specific to eClinicalWorks to avoid potential conflicts.

Consider renaming for clarity:

-export const tokenEhrPatientIdQueryParam = "eclinicalworksPatientIdFromToken";
+export const ECLINICALWORKS_TOKEN_PATIENT_ID_QUERY_PARAM = "eclinicalworksPatientIdFromToken";

This follows the coding guidelines for constant naming (using SCREAMING_SNAKE_CASE for constants).

packages/core/src/external/opensearch/shared/bulk.ts (1)

4-5: Consider making BulkRequest type more specific.

The current BulkRequest type uses Partial<Record<BulkOperation, { _id: string }>> which allows for empty objects. Consider if this is intentional or if at least one operation should be required.

-export type BulkRequest = Partial<Record<BulkOperation, { _id: string }>>;
+export type BulkRequest = Record<BulkOperation, { _id: string }>;

This would ensure at least one operation is always present, but only apply this if it aligns with the expected usage patterns.

packages/core/src/external/fhir/export/string/resources/diagnostic-report.ts (1)

23-26: Consider removing commented code or adding TODO.

There's commented-out code for basedOn field. Consider either removing it if it's not needed or adding a TODO comment explaining why it's commented.

-    // if (report.basedOn) {
-    //   const basedOnStr = formatReferences(report.basedOn, "Based On");
-    //   if (basedOnStr) parts.push(basedOnStr);
-    // }
+    // TODO: Add basedOn field formatting when requirements are clarified
+    // if (report.basedOn) {
+    //   const basedOnStr = formatReferences({ references: report.basedOn, label: "Based On", isDebug });
+    //   if (basedOnStr) parts.push(basedOnStr);
+    // }
packages/api/src/routes/internal/medical/patient-consolidated.ts (1)

49-140: Well-implemented route with good transaction handling.

The route properly validates parameters, uses database transactions for consistency, and includes comprehensive logging. The dry run functionality is valuable for testing.

Consider addressing the scalability concerns mentioned in the comments about moving to a queue-based design for larger patient volumes.

Would you like me to help track the TODO item on line 61 about moving this to an ops/internal command?

packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)

34-34: Extract magic string to a constant.

The magic string "<!empty!>" should be extracted to a named constant for better maintainability and clarity.

+const EMPTY_CODE_PLACEHOLDER = "<!empty!>";
+
 export function formatCodeableConcept({
   concept,
   label,
   skipInternalCodes,
   isDebug = defaultIsDebug,
 }: {
   concept: CodeableConcept | undefined;
   label?: string;
   skipInternalCodes?: boolean | undefined;
   isDebug?: boolean | undefined;
 }): string | undefined {
   if (!concept) return undefined;
 
   const textPre = emptyIfDenied(concept.text);
   const text = textPre ? textPre.trim() : undefined;
 
-  const emptyCode = "<!empty!>";
+  const emptyCode = EMPTY_CODE_PLACEHOLDER;

55-61: Consider simplifying string building logic.

The string building logic could be more concise and functional. Consider using array methods for cleaner code.

-  let codingStr = "";
-  const values = Object.values(codingMap);
-  const sortedValues = values.sort();
-  for (const coding of sortedValues) {
-    const separator = codingStr.length > 0 ? ` ${SEP_BETWEEN_CODING} ` : "";
-    codingStr = codingStr + separator + coding;
-  }
+  const codingStr = Object.values(codingMap)
+    .sort()
+    .join(` ${SEP_BETWEEN_CODING} `);
packages/core/src/external/fhir/export/string/shared/coding.ts (1)

86-88: Consider improving function naming and add JSDoc.

The isInternalCoding function could benefit from better documentation about what constitutes an "internal" coding.

+/**
+ * Checks if a coding uses an internal code system that should be filtered out.
+ * Internal systems start with the OID prefix "urn:oid:1.2.840."
+ * @param coding - The FHIR coding to check
+ * @returns true if the coding uses an internal code system
+ */
 function isInternalCoding(coding: Coding): boolean {
   return coding.system?.startsWith(INTERNAL_CODE_SYSTEM) ?? false;
 }
packages/api/src/external/ehr/eclinicalworks/command/sync-patient.ts (2)

91-96: Improve error message specificity.

The error message "Invalid token source" could be more descriptive to help with debugging.

   if (token.data.source !== eclinicalworksDashSource) {
-    throw new MetriportError("Invalid token source", undefined, {
+    throw new MetriportError(`Invalid token source, expected ${eclinicalworksDashSource}`, undefined, {
       tokenId,
       source: token.data.source,
+      expectedSource: eclinicalworksDashSource,
     });
   }

98-105: Improve error message specificity.

The error message "Invalid token practiceId" could be more descriptive.

   if (tokenPracticeId !== practiceId) {
-    throw new MetriportError("Invalid token practiceId", undefined, {
+    throw new MetriportError(`Token practice ID mismatch, expected ${practiceId}`, undefined, {
       tokenId,
       source: token.data.source,
       tokenPracticeId,
       practiceId,
+      expectedPracticeId: practiceId,
     });
   }
packages/core/src/external/ehr/eclinicalworks/index.ts (1)

28-33: Improve URL construction clarity.

The conditional URL construction for environment could be clearer and more maintainable.

+  private getBaseUrl(environment: EClinicalWorksEnv): string {
+    const subdomain = environment === "production" ? "" : "staging-";
+    return `https://${subdomain}fhir.ecwcloud.com`;
+  }
+
   private constructor(config: EClinicalWorksApiConfig) {
     this.practiceId = config.practiceId;
-    this.baseFhirUrl = `https://${
-      config.environment === "production" ? "" : "staging-"
-    }fhir.ecwcloud.com`;
+    this.baseFhirUrl = this.getBaseUrl(config.environment);
     this.axiosFhirInstance = axios.create({});
     this.token = config.authToken;
   }
packages/core/src/external/fhir/export/string/shared/dosage.ts (1)

40-46: Prefer optional-chaining over boolean short-circuit for join

doseAndRateStr && doseAndRateStr.join(...) works, but optional-chaining conveys the intent more clearly, avoids accidental coercion, and is exactly what the linter is hinting at.

-    doseAndRateStr && doseAndRateStr.join(FIELD_SEPARATOR),
+    doseAndRateStr?.join(FIELD_SEPARATOR),
🧰 Tools
🪛 Biome (1.9.4)

[error] 45-45: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/core/src/external/fhir/export/string/resources/medication-request.ts (1)

22-24: Add a debug label for identifiers to keep output self-describing

When isDebug is enabled the rest of the fields are nicely prefixed (e.g., “Status: …”). Identifiers are currently pushed raw, breaking the consistency of the debug output.

-    const identifierStr = formatIdentifiers({ identifiers: request.identifier });
-    if (identifierStr) parts.push(identifierStr);
+    const identifierStr = formatIdentifiers({ identifiers: request.identifier });
+    if (identifierStr) {
+      parts.push(isDebug ? `Identifier: ${identifierStr}` : identifierStr);
+    }
packages/core/src/command/consolidated/consolidated-get.ts (2)

98-112: Consider surfacing connector errors instead of silently returning rejected promises

getConsolidatedPatientData awaits the connector call and will bubble-up any error (👍), but getConsolidatedPatientDataAsync deliberately fires-and-forgets by returning void and handling errors only through processAsyncError.
If a caller expects to await resolution (e.g., in a background job chain) it will never know that the execution finished/failed.

Two lightweight approaches:

-  connector
-    .execute(payload)
-    .catch(processAsyncError("Failed to get consolidated patient data async", undefined, true));
+  // Return the promise so callers can await *if* they want, while still attaching
+  // the default error-handler when it is not awaited.
+  return connector
+    .execute(payload)
+    .catch(processAsyncError("Failed to get consolidated patient data async", undefined, true));

or keep the current signature but document clearly that the promise is not settled.
Either way, make the contract explicit so downstream code is not surprised.


150-157: Guard against empty bundles before converting to text

If getConsolidatedPatientData eventually returns undefined (e.g., S3 key not found) bundleToString will throw.
A minimal defensive check keeps the helper 100 % safe:

-  const consolidated = await getConsolidatedPatientData({ patient });
-  return bundleToString(consolidated);
+  const consolidated = await getConsolidatedPatientData({ patient });
+  if (!consolidated) return [];
+  return bundleToString(consolidated);
packages/core/src/external/opensearch/text-ingestor.ts (2)

144-156: Chunk ingestion could overshoot the 5-15 MB guideline

The fixed bulkChunkSize = 500 assumes an average 10 KB resource; larger notes/images will blow past the recommended bulk payload, increasing the chance of 413/504 errors.

Consider building chunks based on total serialized size instead of fixed item count (the TODO already hints at this). A quick heuristic:

// pseudo-code
let currentBatch: IngestRequestResource[] = [];
let currentSize = 0;
for (const r of resources) {
  const size = Buffer.byteLength(JSON.stringify(r.content), 'utf8');
  if (currentSize + size > MAX_BATCH_BYTES) flushBatch();
  currentBatch.push(r);
  currentSize += size;
}

This keeps requests within OpenSearch limits and avoids unpredictable failures.


234-239: Minor typo – ‘requeests’

- * NOTE: Assumes all requeests are for the same index and operation!
+ * NOTE: Assumes all requests are for the same index and operation!
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b3a343 and 33790e0.

📒 Files selected for processing (144)
  • packages/api/src/command/hie/unlink-patient-from-organization.ts (1 hunks)
  • packages/api/src/command/jwt-token.ts (2 hunks)
  • packages/api/src/command/medical/patient/consolidated-delete.ts (1 hunks)
  • packages/api/src/command/medical/patient/consolidated-get.ts (1 hunks)
  • packages/api/src/errors/index.ts (1 hunks)
  • packages/api/src/external/carequality/document/process-outbound-document-retrieval-resps.ts (2 hunks)
  • packages/api/src/external/cda/generate-ccd.ts (2 hunks)
  • packages/api/src/external/commonwell/document/document-query.ts (2 hunks)
  • packages/api/src/external/ehr/eclinicalworks/command/sync-patient.ts (1 hunks)
  • packages/api/src/external/ehr/eclinicalworks/shared.ts (1 hunks)
  • packages/api/src/external/ehr/shared/utils/bundle/functions.ts (1 hunks)
  • packages/api/src/external/ehr/shared/utils/client.ts (3 hunks)
  • packages/api/src/external/ehr/shared/utils/jwt-token.ts (3 hunks)
  • packages/api/src/external/ehr/shared/utils/mappings.ts (1 hunks)
  • packages/api/src/external/opensearch/file-search-connector-factory.ts (0 hunks)
  • packages/api/src/routes/ehr/eclinicalworks/auth/middleware.ts (1 hunks)
  • packages/api/src/routes/ehr/eclinicalworks/patient.ts (1 hunks)
  • packages/api/src/routes/ehr/eclinicalworks/routes/dash.ts (1 hunks)
  • packages/api/src/routes/ehr/index.ts (2 hunks)
  • packages/api/src/routes/ehr/shared.ts (1 hunks)
  • packages/api/src/routes/internal/jwt-token/eclinicalworks.ts (1 hunks)
  • packages/api/src/routes/internal/jwt-token/index.ts (2 hunks)
  • packages/api/src/routes/internal/medical/patient-consolidated.ts (1 hunks)
  • packages/api/src/routes/internal/medical/patient.ts (4 hunks)
  • packages/api/src/routes/medical/document.ts (1 hunks)
  • packages/api/src/routes/medical/patient.ts (3 hunks)
  • packages/api/src/shared/config.ts (1 hunks)
  • packages/core/src/command/ai-brief/filter.ts (7 hunks)
  • packages/core/src/command/consolidated/consolidated-filter.ts (5 hunks)
  • packages/core/src/command/consolidated/consolidated-get.ts (3 hunks)
  • packages/core/src/command/consolidated/get-snapshot.ts (1 hunks)
  • packages/core/src/command/consolidated/search/document-reference/ingest.ts (1 hunks)
  • packages/core/src/command/consolidated/search/document-reference/search.ts (2 hunks)
  • packages/core/src/command/consolidated/search/fhir-resource/ingest-lexical.ts (1 hunks)
  • packages/core/src/command/consolidated/search/fhir-resource/ingest-semantic.ts (1 hunks)
  • packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-direct.ts (1 hunks)
  • packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-factory.ts (1 hunks)
  • packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts (1 hunks)
  • packages/core/src/command/consolidated/search/fhir-resource/search-lexical.ts (1 hunks)
  • packages/core/src/command/consolidated/search/fhir-resource/search-semantic.ts (5 hunks)
  • packages/core/src/command/consolidated/snapshot-on-s3.ts (1 hunks)
  • packages/core/src/domain/ai-brief/modify-resources.ts (2 hunks)
  • packages/core/src/external/aws/document-signing/bulk-sign.ts (1 hunks)
  • packages/core/src/external/ehr/bundle/job/create-resource-diff-bundles/steps/compute/ehr-compute-resource-diff-bundles-local.ts (2 hunks)
  • packages/core/src/external/ehr/eclinicalworks/index.ts (1 hunks)
  • packages/core/src/external/fhir/__tests__/bundle.ts (1 hunks)
  • packages/core/src/external/fhir/codeable-concept.ts (1 hunks)
  • packages/core/src/external/fhir/consolidated/consolidated.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/bundle-to-string.ts (6 hunks)
  • packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/allergy-intolerance.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/communication.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/composition.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/condition.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/consent.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/coverage.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/diagnostic-report.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/document-reference.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/encounter.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/family-member-history.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/immunization.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/location.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/medication-administration.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/medication-dispense.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/medication-request.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/medication-statement.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/medication.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/observation.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/organization.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/patient.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/practitioner.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/procedure.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/resources/related-person.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/__tests__/codeable-concept.test.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/__tests__/timing.test.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/address.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/age.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/annotation.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/attachment.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/code-display.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/coding.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/debug.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/deny.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/dosage.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/duration.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/human-name.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/identifier.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/narrative.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/numeric.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/period.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/quantity.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/range.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/ratio.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/reference.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/string.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/telecom.ts (1 hunks)
  • packages/core/src/external/fhir/export/string/shared/timing.ts (1 hunks)
  • packages/core/src/external/fhir/normalization/resources/encounter.ts (1 hunks)
  • packages/core/src/external/fhir/resources/diagnostic-report.ts (1 hunks)
  • packages/core/src/external/html/remove-tags.ts (1 hunks)
  • packages/core/src/external/opensearch/cda.ts (0 hunks)
  • packages/core/src/external/opensearch/file-searcher.ts (0 hunks)
  • packages/core/src/external/opensearch/file/file-ingestor-direct.ts (3 hunks)
  • packages/core/src/external/opensearch/file/file-ingestor-sqs.ts (1 hunks)
  • packages/core/src/external/opensearch/file/file-ingestor.ts (1 hunks)
  • packages/core/src/external/opensearch/file/file-remover-direct.ts (1 hunks)
  • packages/core/src/external/opensearch/file/file-search-connector-factory.ts (3 hunks)
  • packages/core/src/external/opensearch/file/file-searcher-direct.ts (2 hunks)
  • packages/core/src/external/opensearch/file/file-searcher.ts (1 hunks)
  • packages/core/src/external/opensearch/index-based-on-file.ts (1 hunks)
  • packages/core/src/external/opensearch/index-based-on-resource.ts (1 hunks)
  • packages/core/src/external/opensearch/index.ts (1 hunks)
  • packages/core/src/external/opensearch/lexical/lexical-search.ts (1 hunks)
  • packages/core/src/external/opensearch/lexical/lexical-searcher.ts (1 hunks)
  • packages/core/src/external/opensearch/semantic/hybrid-create.ts (1 hunks)
  • packages/core/src/external/opensearch/semantic/ingest.ts (0 hunks)
  • packages/core/src/external/opensearch/semantic/semantic-searcher.ts (5 hunks)
  • packages/core/src/external/opensearch/semantic/shared.ts (0 hunks)
  • packages/core/src/external/opensearch/shared/bulk.ts (1 hunks)
  • packages/core/src/external/opensearch/shared/delete.ts (1 hunks)
  • packages/core/src/external/opensearch/shared/filters.ts (1 hunks)
  • packages/core/src/external/opensearch/shared/id.ts (1 hunks)
  • packages/core/src/external/opensearch/shared/log.ts (1 hunks)
  • packages/core/src/external/opensearch/text-ingestor-direct.ts (0 hunks)
  • packages/core/src/external/opensearch/text-ingestor.ts (1 hunks)
  • packages/core/src/util/config.ts (1 hunks)
  • packages/core/src/util/error/shared.ts (1 hunks)
  • packages/infra/config/env-config.ts (1 hunks)
  • packages/infra/lib/api-stack.ts (1 hunks)
  • packages/infra/lib/api-stack/api-service.ts (2 hunks)
  • packages/infra/lib/api-stack/ccda-search-connector.ts (1 hunks)
  • packages/lambdas/src/shared/ehr.ts (1 hunks)
  • packages/lambdas/src/sqs-to-opensearch-xml.ts (2 hunks)
  • packages/shared/src/interface/external/ehr/eclinicalworks/index.ts (1 hunks)
  • packages/shared/src/interface/external/ehr/eclinicalworks/jwt-token.ts (1 hunks)
  • packages/shared/src/interface/external/ehr/source.ts (1 hunks)
  • packages/utils/src/fhir/ai-brief/build-slim-bundle.ts (1 hunks)
  • packages/utils/src/open-search/cleanup.ts (1 hunks)
  • packages/utils/src/open-search/re-populate.ts (1 hunks)
  • packages/utils/src/open-search/semantic-ingest.ts (2 hunks)
  • packages/utils/src/open-search/semantic-search.ts (1 hunks)
  • packages/utils/src/open-search/semantic-text-from-consolidated.ts (2 hunks)
  • packages/utils/src/shared/sentry.ts (1 hunks)
💤 Files with no reviewable changes (6)
  • packages/core/src/external/opensearch/semantic/shared.ts
  • packages/api/src/external/opensearch/file-search-connector-factory.ts
  • packages/core/src/external/opensearch/cda.ts
  • packages/core/src/external/opensearch/file-searcher.ts
  • packages/core/src/external/opensearch/text-ingestor-direct.ts
  • packages/core/src/external/opensearch/semantic/ingest.ts
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.ts`: - Use the Onion Pattern to organize a package's code in layers - Try to use immutable code and avoid sharing state across different functions, objects, and systems - Try...

**/*.ts: - Use the Onion Pattern to organize a package's code in layers

  • Try to use immutable code and avoid sharing state across different functions, objects, and systems
  • Try to build code that's idempotent whenever possible
  • Prefer functional programming style functions: small, deterministic, 1 input, 1 output
  • Minimize coupling / dependencies
  • Avoid modifying objects received as parameter
  • Only add comments to code to explain why something was done, not how it works
  • Naming
    • classes, enums: PascalCase
    • constants, variables, functions: camelCase
    • file names: kebab-case
    • table and column names: snake_case
    • Use meaningful names, so whoever is reading the code understands what it means
    • Don’t use negative names, like notEnabled, prefer isDisabled
    • For numeric values, if the type doesn’t convey the unit, add the unit to the name
  • Typescript
    • Use types
    • Prefer const instead of let
    • Avoid any and casting from any to other types
    • Type predicates: only applicable to narrow down the type, not to force a complete type conversion
    • Prefer deconstructing parameters for functions instead of multiple parameters that might be of
      the same type
    • Don’t use null inside the app, only on code interacting with external interfaces/services,
      like DB and HTTP; convert to undefined before sending inwards into the code
    • Use async/await instead of .then()
    • Use the strict equality operator ===, don’t use abstract equality operator ==
    • When calling a Promise-returning function asynchronously (i.e., not awaiting), use .catch() to
      handle errors (see processAsyncError and emptyFunction depending on the case)
    • Date and Time
      • Always use buildDayjs() to create dayjs instances
      • Prefer dayjs.duration(...) to create duration consts and keep them as duration
  • Prefer Nullish Coalesce (??) than the OR operator (||) to provide a d 10000 efault value
  • Avoid creating arrow functions
  • Use truthy syntax instead of in - i.e., if (data.link) not if ('link' in data)
  • Error handling
    • Pass the original error as the new one’s cause so the stack trace is persisted
    • Error messages should have a static message - add dynamic data to MetriportError's additionalInfo prop
    • Avoid sending multiple events to Sentry for a single error
  • Global constants and variables
    • Move literals to constants declared after imports when possible (avoid magic numbers)
    • Avoid shared, global objects
  • Avoid using console.log and console.error in packages other than utils, infra and shared,
    and try to use out().log instead
  • Avoid multi-line logs
    • don't send objects as a second parameter to console.log() or out().log()
    • don't create multi-line strings when using JSON.stringify()
  • Use eslint to enforce code style
  • Use prettier to format code
  • max column length is 100 chars
  • multi-line comments use /** */
  • scripts: top-level comments go after the import
  • packages/core/src/external/opensearch/file/file-remover-direct.ts
  • packages/core/src/external/fhir/normalization/resources/encounter.ts
  • packages/utils/src/open-search/cleanup.ts
  • packages/core/src/external/fhir/export/string/shared/debug.ts
  • packages/api/src/routes/internal/jwt-token/index.ts
  • packages/core/src/external/ehr/bundle/job/create-resource-diff-bundles/steps/compute/ehr-compute-resource-diff-bundles-local.ts
  • packages/utils/src/open-search/semantic-search.ts
  • packages/core/src/external/opensearch/file/file-ingestor-sqs.ts
  • packages/lambdas/src/sqs-to-opensearch-xml.ts
  • packages/api/src/external/ehr/shared/utils/bundle/functions.ts
  • packages/lambdas/src/shared/ehr.ts
  • packages/utils/src/open-search/re-populate.ts
  • packages/shared/src/interface/external/ehr/eclinicalworks/index.ts
  • packages/core/src/external/opensearch/file/file-search-connector-factory.ts
  • packages/api/src/routes/medical/document.ts
  • packages/shared/src/interface/external/ehr/source.ts
  • packages/api/src/errors/index.ts
  • packages/api/src/external/ehr/shared/utils/mappings.ts
  • packages/core/src/command/consolidated/snapshot-on-s3.ts
  • packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-factory.ts
  • packages/api/src/command/medical/patient/consolidated-delete.ts
  • packages/core/src/external/fhir/export/string/shared/code-display.ts
  • packages/infra/lib/api-stack/ccda-search-connector.ts
  • packages/infra/lib/api-stack.ts
  • packages/core/src/util/config.ts
  • packages/core/src/external/opensearch/shared/id.ts
  • packages/core/src/domain/ai-brief/modify-resources.ts
  • packages/utils/src/shared/sentry.ts
  • packages/api/src/routes/ehr/index.ts
  • packages/core/src/external/fhir/codeable-concept.ts
  • packages/core/src/external/fhir/__tests__/bundle.ts
  • packages/api/src/external/ehr/eclinicalworks/shared.ts
  • packages/core/src/external/fhir/export/string/shared/string.ts
  • packages/core/src/command/consolidated/get-snapshot.ts
  • packages/core/src/external/opensearch/shared/filters.ts
  • packages/infra/lib/api-stack/api-service.ts
  • packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts
  • packages/infra/config/env-config.ts
  • packages/core/src/external/fhir/export/string/shared/__tests__/timing.test.ts
  • packages/api/src/external/commonwell/document/document-query.ts
  • packages/core/src/external/opensearch/semantic/hybrid-create.ts
  • packages/api/src/shared/config.ts
  • packages/core/src/external/fhir/export/string/shared/age.ts
  • packages/core/src/command/consolidated/consolidated-filter.ts
  • packages/api/src/command/hie/unlink-patient-from-organization.ts
  • packages/core/src/external/opensearch/index-based-on-resource.ts
  • packages/core/src/external/fhir/export/string/shared/range.ts
  • packages/api/src/routes/ehr/eclinicalworks/patient.ts
  • packages/api/src/command/jwt-token.ts
  • packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts
  • packages/core/src/external/opensearch/shared/delete.ts
  • packages/shared/src/interface/external/ehr/eclinicalworks/jwt-token.ts
  • packages/api/src/external/ehr/shared/utils/jwt-token.ts
  • packages/core/src/external/fhir/export/string/shared/narrative.ts
  • packages/core/src/external/fhir/export/string/resources/medication.ts
  • packages/api/src/routes/ehr/eclinicalworks/routes/dash.ts
  • packages/core/src/external/fhir/export/string/resources/communication.ts
  • packages/api/src/command/medical/patient/consolidated-get.ts
  • packages/core/src/external/opensearch/shared/log.ts
  • packages/core/src/util/error/shared.ts
  • packages/core/src/external/fhir/export/string/resources/coverage.ts
  • packages/utils/src/open-search/semantic-text-from-consolidated.ts
  • packages/core/src/external/fhir/export/string/resources/procedure.ts
  • packages/core/src/external/aws/document-signing/bulk-sign.ts
  • packages/core/src/external/fhir/export/string/resources/patient.ts
  • packages/core/src/external/fhir/export/string/shared/ratio.ts
  • packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-direct.ts
  • packages/core/src/external/fhir/export/string/resources/related-person.ts
  • packages/core/src/command/consolidated/search/fhir-resource/search-lexical.ts
  • packages/core/src/external/fhir/export/string/resources/practitioner.ts
  • packages/core/src/external/fhir/export/string/shared/reference.ts
  • packages/api/src/routes/internal/jwt-token/eclinicalworks.ts
  • packages/core/src/external/fhir/export/string/resources/medication-administration.ts
  • packages/core/src/external/opensearch/lexical/lexical-search.ts
  • packages/core/src/external/fhir/export/string/shared/quantity.ts
  • packages/core/src/external/fhir/export/string/shared/period.ts
  • packages/api/src/routes/ehr/shared.ts
  • packages/core/src/command/consolidated/search/fhir-resource/ingest-semantic.ts
  • packages/core/src/external/fhir/export/string/resources/medication-statement.ts
  • packages/core/src/external/opensearch/semantic/semantic-searcher.ts
  • packages/utils/src/fhir/ai-brief/build-slim-bundle.ts
  • packages/core/src/external/opensearch/file/file-ingestor.ts
  • packages/core/src/external/opensearch/file/file-ingestor-direct.ts
  • packages/core/src/command/consolidated/search/document-reference/ingest.ts
  • packages/core/src/external/fhir/export/string/resources/composition.ts
  • packages/core/src/external/fhir/resources/diagnostic-report.ts
  • packages/core/src/external/fhir/export/string/bundle-to-string.ts
  • packages/core/src/external/fhir/export/string/resources/encounter.ts
  • packages/core/src/external/opensearch/lexical/lexical-searcher.ts
  • packages/core/src/external/fhir/export/string/resources/consent.ts
  • packages/core/src/command/consolidated/search/fhir-resource/search-semantic.ts
  • packages/api/src/external/cda/generate-ccd.ts
  • packages/core/src/external/fhir/export/string/resources/family-member-history.ts
  • packages/core/src/external/fhir/export/string/resources/immunization.ts
  • packages/core/src/external/fhir/export/string/resources/medication-dispense.ts
  • packages/api/src/routes/internal/medical/patient.ts
  • packages/core/src/external/html/remove-tags.ts
  • packages/api/src/external/ehr/shared/utils/client.ts
  • packages/core/src/external/opensearch/file/file-searcher.ts
  • packages/core/src/external/fhir/export/string/resources/observation.ts
  • packages/core/src/external/fhir/export/string/resources/document-reference.ts
  • packages/api/src/routes/medical/patient.ts
  • packages/api/src/external/carequality/document/process-outbound-document-retrieval-resps.ts
  • packages/core/src/external/fhir/export/string/shared/duration.ts
  • packages/core/src/external/fhir/consolidated/consolidated.ts
  • packages/core/src/command/consolidated/search/document-reference/search.ts
  • packages/core/src/external/fhir/export/string/shared/annotation.ts
  • packages/core/src/external/fhir/export/string/resources/condition.ts
  • packages/core/src/external/fhir/export/string/resources/location.ts
  • packages/core/src/external/opensearch/file/file-searcher-direct.ts
  • packages/core/src/external/fhir/export/string/shared/attachment.ts
  • packages/core/src/external/fhir/export/string/shared/numeric.ts
  • packages/core/src/external/fhir/export/string/shared/identifier.ts
  • packages/core/src/external/fhir/export/string/shared/human-name.ts
  • packages/api/src/external/ehr/eclinicalworks/command/sync-patient.ts
  • packages/core/src/external/opensearch/shared/bulk.ts
  • packages/core/src/external/fhir/export/string/shared/deny.ts
  • packages/core/src/external/fhir/export/string/resources/diagnostic-report.ts
  • packages/core/src/external/fhir/export/string/resources/allergy-intolerance.ts
  • packages/core/src/external/fhir/export/string/resources/organization.ts
  • packages/core/src/external/fhir/export/string/shared/address.ts
  • packages/utils/src/open-search/semantic-ingest.ts
  • packages/api/src/routes/ehr/eclinicalworks/auth/middleware.ts
  • packages/core/src/command/consolidated/search/fhir-resource/ingest-lexical.ts
  • packages/core/src/external/fhir/export/string/shared/codeable-concept.ts
  • packages/core/src/external/fhir/export/string/shared/__tests__/codeable-concept.test.ts
  • packages/api/src/routes/internal/medical/patient-consolidated.ts
  • packages/core/src/external/ehr/eclinicalworks/index.ts
  • packages/core/src/external/fhir/export/string/resources/medication-request.ts
  • packages/core/src/external/fhir/export/string/shared/dosage.ts
  • packages/core/src/external/fhir/export/string/shared/coding.ts
  • packages/core/src/command/consolidated/consolidated-get.ts
  • packages/core/src/external/fhir/export/string/shared/timing.ts
  • packages/core/src/external/fhir/export/string/shared/telecom.ts
  • packages/core/src/command/ai-brief/filter.ts
  • packages/core/src/external/opensearch/index.ts
  • packages/core/src/external/opensearch/index-based-on-file.ts
  • packages/core/src/external/opensearch/text-ingestor.ts
🧠 Learnings (8)
packages/api/src/command/medical/patient/consolidated-delete.ts (1)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/api/src/routes/internal/medical/patient-consolidated.ts:141-174
Timestamp: 2025-05-20T21:26:26.804Z
Learning: The functionality introduced in packages/api/src/routes/internal/medical/patient-consolidated.ts is planned to be refactored in downstream PR #3857, including improvements to error handling and validation.
packages/api/src/routes/ehr/eclinicalworks/patient.ts (1)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/api/src/routes/internal/medical/patient-consolidated.ts:141-174
Timestamp: 2025-05-20T21:26:26.804Z
Learning: The functionality introduced in packages/api/src/routes/internal/medical/patient-consolidated.ts is planned to be refactored in downstream PR #3857, including improvements to error handling and validation.
packages/api/src/command/medical/patient/consolidated-get.ts (2)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/api/src/routes/internal/medical/patient-consolidated.ts:141-174
Timestamp: 2025-05-20T21:26:26.804Z
Learning: The functionality introduced in packages/api/src/routes/internal/medical/patient-consolidated.ts is planned to be refactored in downstream PR #3857, including improvements to error handling and validation.
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/core/src/command/consolidated/search/fhir-resource/search-semantic.ts:36-36
Timestamp: 2025-05-19T13:53:09.828Z
Learning: In the `getConsolidatedPatientData` function from `@metriport/core/command/consolidated/consolidated-get`, only the `patient` parameter is required. Other parameters like `requestId`, `resources`, `dateFrom`, `dateTo`, `fromDashboard`, and `forceDataFromFhir` are all optional.
packages/api/src/routes/internal/medical/patient.ts (1)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/api/src/routes/internal/medical/patient-consolidated.ts:141-174
Timestamp: 2025-05-20T21:26:26.804Z
Learning: The functionality introduced in packages/api/src/routes/internal/medical/patient-consolidated.ts is planned to be refactored in downstream PR #3857, including improvements to error handling and validation.
packages/core/src/external/html/remove-tags.ts (2)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/core/src/external/opensearch/file/file-ingestor-direct.ts:91-100
Timestamp: 2025-05-19T14:09:12.444Z
Learning: In packages/core/src/external/html/remove-tags.ts, the `removeHtmlTags` function has an `isRemoveNewLinesAndSpaces` parameter that defaults to true, which automatically handles the removal of newlines, tabs, carriage returns, and multiple spaces without needing to explicitly set this parameter when calling the function.
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/core/src/external/opensearch/file/file-ingestor-direct.ts:91-100
Timestamp: 2025-05-19T14:09:12.444Z
Learning: In packages/core/src/external/html/remove-tags.ts, the `removeHtmlTags` function has an `isRemoveNewLinesAndSpaces` parameter that defaults to true, which automatically handles the removal of newlines, tabs, carriage returns, and multiple spaces without needing to explicitly set this parameter when calling the function.
packages/api/src/routes/medical/patient.ts (1)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/api/src/routes/internal/medical/patient-consolidated.ts:141-174
Timestamp: 2025-05-20T21:26:26.804Z
Learning: The functionality introduced in packages/api/src/routes/internal/medical/patient-consolidated.ts is planned to be refactored in downstream PR #3857, including improvements to error handling and validation.
packages/api/src/routes/internal/medical/patient-consolidated.ts (1)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/api/src/routes/internal/medical/patient-consolidated.ts:141-174
Timestamp: 2025-05-20T21:26:26.804Z
Learning: The functionality introduced in packages/api/src/routes/internal/medical/patient-consolidated.ts is planned to be refactored in downstream PR #3857, including improvements to error handling and validation.
packages/core/src/command/consolidated/consolidated-get.ts (2)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/api/src/routes/internal/medical/patient-consolidated.ts:141-174
Timestamp: 2025-05-20T21:26:26.804Z
Learning: The functionality introduced in packages/api/src/routes/internal/medical/patient-consolidated.ts is planned to be refactored in downstream PR #3857, including improvements to error handling and validation.
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/core/src/command/consolidated/search/fhir-resource/search-semantic.ts:36-36
Timestamp: 2025-05-19T13:53:09.828Z
Learning: In the `getConsolidatedPatientData` function from `@metriport/core/command/consolidated/consolidated-get`, only the `patient` parameter is required. Other parameters like `requestId`, `resources`, `dateFrom`, `dateTo`, `fromDashboard`, and `forceDataFromFhir` are all optional.
🧬 Code Graph Analysis (65)
packages/core/src/external/ehr/bundle/job/create-resource-diff-bundles/steps/compute/ehr-compute-resource-diff-bundles-local.ts (1)
packages/core/src/command/consolidated/consolidated-get.ts (1)
  • getConsolidatedFile (43-61)
packages/core/src/external/opensearch/file/file-search-connector-factory.ts (1)
packages/core/src/util/config.ts (1)
  • Config (9-226)
packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-factory.ts (2)
packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts (1)
  • SearchConsolidated (13-15)
packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-direct.ts (1)
  • SearchConsolidatedDirect (31-48)
packages/core/src/external/fhir/export/string/shared/code-display.ts (1)
packages/core/src/external/fhir/codeable-concept.ts (1)
  • isUsefulDisplay (44-51)
packages/api/src/external/ehr/eclinicalworks/shared.ts (3)
packages/api/src/shared/config.ts (1)
  • getEClinicalWorksEnv (335-337)
packages/core/src/external/ehr/eclinicalworks/index.ts (2)
  • EClinicalWorksEnv (15-15)
  • isEClinicalWorksEnv (16-18)
packages/api/src/external/ehr/shared/utils/client.ts (1)
  • EhrPerPracticeParams (31-31)
packages/core/src/external/fhir/export/string/shared/string.ts (1)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/shared/age.ts (1)
packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
  • formatQuantity (11-24)
packages/core/src/command/consolidated/consolidated-filter.ts (3)
packages/core/src/command/consolidated/consolidated-get.ts (1)
  • getConsolidatedFile (43-61)
packages/shared/src/common/date.ts (1)
  • elapsedTimeFromNow (63-68)
packages/core/src/external/fhir/shared/bundle.ts (1)
  • buildBundleEntry (187-193)
packages/core/src/external/opensearch/index-based-on-resource.ts (2)
packages/core/src/external/opensearch/index-based-on-file.ts (2)
  • IndexFields (3-8)
  • SearchResult (10-12)
packages/core/src/external/opensearch/index.ts (1)
  • contentFieldName (1-1)
packages/core/src/external/fhir/export/string/shared/range.ts (3)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
  • defaultIsDebug (1-1)
packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
  • formatQuantity (11-24)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/api/src/command/jwt-token.ts (2)
packages/api/src/domain/jwt-token.ts (1)
  • JwtToken (30-30)
packages/shared/src/index.ts (1)
  • NotFoundError (41-41)
packages/core/src/external/opensearch/shared/delete.ts (1)
packages/core/src/external/opensearch/shared/filters.ts (1)
  • getPatientFilters (1-3)
packages/api/src/external/ehr/shared/utils/jwt-token.ts (2)
packages/shared/src/interface/external/ehr/eclinicalworks/jwt-token.ts (2)
  • eclinicalworksDashSource (4-4)
  • EClinicalWorksDashJwtTokenData (10-10)
packages/shared/src/interface/external/ehr/healthie/jwt-token.ts (1)
  • HealthieDashJwtTokenData (10-10)
packages/core/src/external/fhir/export/string/shared/narrative.ts (2)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
  • defaultIsDebug (1-1)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/resources/medication.ts (6)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (1)
  • FHIRResourceToString (8-16)
packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
  • formatIdentifiers (5-19)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)
  • formatCodeableConcepts (78-96)
  • formatCodeableConcept (18-68)
packages/core/src/external/fhir/export/string/shared/reference.ts (1)
  • formatReferences (8-26)
packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
  • formatQuantity (11-24)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/api/src/routes/ehr/eclinicalworks/routes/dash.ts (2)
packages/api/src/routes/ehr/shared.ts (4)
  • documentDownloadUrlRegex (48-48)
  • processPatientRoute (91-100)
  • processEhrPatientId (135-154)
  • processDocumentRoute (102-111)
packages/api/src/routes/ehr/eclinicalworks/auth/middleware.ts (3)
  • processPatientRoute (39-41)
  • tokenEhrPatientIdQueryParam (12-12)
  • processDocumentRoute (43-45)
packages/core/src/external/opensearch/shared/log.ts (1)
packages/shared/src/index.ts (1)
  • emptyFunction (7-7)
packages/core/src/util/error/shared.ts (3)
packages/api/src/errors/index.ts (2)
  • processAsyncError (13-20)
  • getErrorMessage (6-8)
packages/shared/src/index.ts (2)
  • BadRequestError (39-39)
  • NotFoundError (41-41)
packages/lambdas/src/shared/capture.ts (1)
  • capture (18-103)
packages/utils/src/open-search/semantic-text-from-consolidated.ts (5)
packages/shared/src/index.ts (1)
  • sleep (13-13)
packages/core/src/external/fhir/export/string/bundle-to-string.ts (2)
  • FhirResourceToText (116-120)
  • bundleToString (131-145)
packages/api-sdk/src/medical/client/metriport.ts (1)
  • MetriportMedicalApi (85-902)
packages/core/src/command/patient-loader-metriport-api.ts (1)
  • getDomainFromDTO (112-141)
packages/core/src/command/consolidated/consolidated-get.ts (1)
  • getConsolidatedAsText (150-157)
packages/core/src/external/fhir/export/string/resources/patient.ts (4)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (1)
  • FHIRResourceToString (8-16)
packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
  • formatIdentifiers (5-19)
packages/core/src/external/fhir/export/string/shared/human-name.ts (1)
  • formatHumanNames (14-31)
packages/core/src/external/fhir/export/string/shared/address.ts (1)
  • formatAddresses (11-27)
packages/core/src/external/fhir/export/string/shared/ratio.ts (3)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
  • defaultIsDebug (1-1)
packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
  • formatQuantity (11-24)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/resources/related-person.ts (7)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
  • FHIRResourceToString (8-16)
  • defaultHasMinimumData (3-3)
packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
  • formatIdentifiers (5-19)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
  • formatCodeableConcepts (78-96)
packages/core/src/external/fhir/export/string/shared/human-name.ts (1)
  • formatHumanNames (14-31)
packages/core/src/external/fhir/export/string/shared/telecom.ts (1)
  • formatTelecoms (12-27)
packages/core/src/external/fhir/export/string/shared/address.ts (1)
  • formatAddresses (11-27)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/resources/practitioner.ts (7)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (1)
  • FHIRResourceToString (8-16)
packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
  • formatNpiIdentifiers (52-58)
packages/core/src/external/fhir/export/string/shared/human-name.ts (1)
  • formatHumanNames (14-31)
packages/core/src/external/fhir/export/string/shared/telecom.ts (1)
  • formatTelecoms (12-27)
packages/core/src/external/fhir/export/string/shared/address.ts (1)
  • formatAddresses (11-27)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
  • formatCodeableConcept (18-68)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/shared/reference.ts (2)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
  • defaultIsDebug (1-1)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/api/src/routes/internal/jwt-token/eclinicalworks.ts (2)
packages/api/src/external/ehr/shared/utils/jwt-token.ts (2)
  • checkJwtToken (74-88)
  • saveJwtToken (90-107)
packages/shared/src/interface/external/ehr/eclinicalworks/jwt-token.ts (2)
  • eclinicalworksDashSource (4-4)
  • eclinicalworksDashJwtTokenDataSchema (5-9)
packages/core/src/external/opensearch/lexical/lexical-search.ts (2)
packages/core/src/external/opensearch/index.ts (1)
  • contentFieldName (1-1)
packages/core/src/external/opensearch/shared/filters.ts (1)
  • getPatientFilters (1-3)
packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
  • defaultIsDebug (1-1)
packages/core/src/external/fhir/export/string/shared/period.ts (2)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
  • defaultIsDebug (1-1)
packages/core/src/domain/patient.ts (1)
  • Period (18-26)
packages/api/src/routes/ehr/shared.ts (3)
packages/api/src/domain/jwt-token.ts (1)
  • JwtTokenData (21-21)
packages/api/src/command/jwt-token.ts (1)
  • getJwtToken (26-35)
packages/shared/src/common/date.ts (1)
  • buildDayjs (70-72)
packages/core/src/command/consolidated/search/fhir-resource/ingest-semantic.ts (3)
packages/core/src/external/opensearch/shared/bulk.ts (1)
  • OnBulkItemError (25-25)
packages/core/src/command/consolidated/consolidated-get.ts (1)
  • getConsolidatedAsText (150-157)
packages/core/src/external/opensearch/text-ingestor.ts (2)
  • OpenSearchTextIngestor (59-224)
  • convertFhirResourceToTextToIngestRequestResource (241-249)
packages/core/src/external/opensearch/semantic/semantic-searcher.ts (1)
packages/core/src/external/opensearch/index.ts (3)
  • OpenSearchConfigDirectAccess (7-11)
  • OpenSearchResponse (21-25)
  • OpenSearchResponseHit (14-19)
packages/core/src/external/opensearch/file/file-ingestor.ts (2)
packages/core/src/external/opensearch/index.ts (1)
  • OpenSearchConfig (3-6)
packages/infra/config/example.ts (1)
  • config (8-228)
packages/core/src/external/opensearch/file/file-ingestor-direct.ts (1)
packages/core/src/external/html/remove-tags.ts (1)
  • removeHtmlTags (41-91)
packages/core/src/command/consolidated/search/document-reference/ingest.ts (1)
packages/core/src/external/opensearch/file/file-search-connector-factory.ts (1)
  • makeSearchServiceIngest (10-30)
packages/core/src/external/fhir/export/string/bundle-to-string.ts (7)
packages/core/src/external/fhir/export/string/resources/consent.ts (1)
  • ConsentToString (20-220)
packages/core/src/external/fhir/export/string/resources/composition.ts (1)
  • CompositionToString (13-136)
packages/core/src/external/fhir/export/string/resources/communication.ts (1)
  • CommunicationToString (12-117)
packages/core/src/external/fhir/export/string/resources/coverage.ts (1)
  • CoverageToString (14-143)
packages/core/src/external/fhir/export/string/resources/document-reference.ts (1)
  • DocumentReferenceToString (13-162)
packages/core/src/external/fhir/export/string/resources/related-person.ts (1)
  • RelatedPersonToString (13-92)
packages/core/src/external/fhir/export/string/resources/patient.ts (1)
  • PatientToString (11-30)
packages/core/src/external/fhir/export/string/resources/encounter.ts (5)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
  • FHIRResourceToString (8-16)
  • defaultHasMinimumData (3-3)
packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
  • formatIdentifiers (5-19)
packages/core/src/external/fhir/export/string/shared/deny.ts (1)
  • emptyIfDenied (9-15)
packages/core/src/external/fhir/export/string/shared/coding.ts (1)
  • formatCoding (42-65)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
  • formatCodeableConcepts (78-96)
packages/core/src/external/fhir/export/string/resources/family-member-history.ts (6)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
  • FHIRResourceToString (8-16)
  • defaultHasMinimumData (3-3)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)
  • formatCodeableConcepts (78-96)
  • formatCodeableConcept (18-68)
packages/core/src/external/fhir/export/string/shared/period.ts (1)
  • formatPeriod (11-25)
packages/core/src/external/fhir/export/string/shared/annotation.ts (1)
  • formatAnnotations (5-21)
packages/core/src/external/fhir/export/string/shared/age.ts (1)
  • formatAge (8-18)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/resources/medication-dispense.ts (6)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
  • FHIRResourceToString (8-16)
  • defaultHasMinimumData (3-3)
packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
  • formatIdentifiers (5-19)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
  • formatCodeableConcept (18-68)
packages/core/src/external/fhir/export/string/shared/reference.ts (2)
  • formatReference (28-41)
  • formatReferences (8-26)
packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
  • formatQuantity (11-24)
packages/core/src/external/fhir/export/string/shared/annotation.ts (1)
  • formatAnnotations (5-21)
packages/api/src/external/ehr/shared/utils/client.ts (5)
packages/core/src/external/ehr/athenahealth/index.ts (1)
  • AthenaEnv (93-93)
packages/core/src/external/ehr/elation/index.ts (1)
  • ElationEnv (54-54)
packages/core/src/external/ehr/canvas/index.ts (1)
  • CanvasEnv (75-75)
packages/core/src/external/ehr/healthie/index.ts (1)
  • HealthieEnv (40-40)
packages/core/src/external/ehr/eclinicalworks/index.ts (1)
  • EClinicalWorksEnv (15-15)
packages/core/src/external/fhir/export/string/resources/observation.ts (6)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (1)
  • FHIRResourceToString (8-16)
packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
  • formatIdentifiers (5-19)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)
  • formatCodeableConcepts (78-96)
  • formatCodeableConcept (18-68)
packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
  • formatQuantity (11-24)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/shared/reference.ts (1)
  • formatReferences (8-26)
packages/api/src/routes/medical/patient.ts (1)
packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-factory.ts (1)
  • makeSearchConsolidated (5-11)
packages/api/src/external/carequality/document/process-outbound-document-retrieval-resps.ts (1)
packages/core/src/command/consolidated/search/document-reference/ingest.ts (1)
  • ingestIntoSearchEngine (7-49)
packages/core/src/external/fhir/export/string/shared/duration.ts (1)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
  • defaultIsDebug (1-1)
packages/core/src/external/fhir/export/string/shared/annotation.ts (2)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
  • defaultIsDebug (1-1)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/resources/condition.ts (10)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
  • FHIRResourceToString (8-16)
  • defaultHasMinimumData (3-3)
packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
  • formatIdentifiers (5-19)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)
  • formatCodeableConcept (18-68)
  • formatCodeableConcepts (78-96)
packages/core/src/external/fhir/export/string/shared/reference.ts (2)
  • formatReference (28-41)
  • formatReferences (8-26)
packages/core/src/external/fhir/export/string/shared/age.ts (1)
  • formatAge (8-18)
packages/core/src/external/fhir/export/string/shared/period.ts (1)
  • formatPeriod (11-25)
packages/core/src/external/fhir/export/string/shared/range.ts (1)
  • formatRange (10-33)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/shared/annotation.ts (1)
  • formatAnnotations (5-21)
packages/core/src/external/fhir/export/string/shared/narrative.ts (1)
  • formatNarrative (10-28)
packages/core/src/external/fhir/export/string/resources/location.ts (7)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
  • FHIRResourceToString (8-16)
  • defaultHasMinimumData (3-3)
packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
  • formatIdentifiers (5-19)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)
  • formatCodeableConcepts (78-96)
  • formatCodeableConcept (18-68)
packages/core/src/external/fhir/export/string/shared/telecom.ts (1)
  • formatTelecoms (12-27)
packages/core/src/external/fhir/export/string/shared/address.ts (1)
  • formatAddress (29-50)
packages/core/src/external/fhir/export/string/shared/reference.ts (1)
  • formatReference (28-41)
packages/core/src/external/opensearch/file/file-searcher-direct.ts (2)
packages/core/src/external/opensearch/index.ts (2)
  • OpenSearchConfigDirectAccess (7-11)
  • OpenSearchResponse (21-25)
packages/core/src/external/opensearch/index-based-on-resource.ts (1)
  • SearchResult (19-19)
packages/core/src/external/fhir/export/string/shared/attachment.ts (3)
packages/core/src/util/mime.ts (1)
  • TXT_MIME_TYPE (39-39)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
  • defaultIsDebug (1-1)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/shared/human-name.ts (2)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
  • defaultIsDebug (1-1)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/opensearch/shared/bulk.ts (2)
packages/core/src/external/opensearch/text-ingestor.ts (2)
  • IngestRequestResource (37-37)
  • IngestRequest (36-36)
packages/core/src/external/opensearch/shared/id.ts (1)
  • getEntryId (9-11)
packages/core/src/external/fhir/export/string/resources/diagnostic-report.ts (9)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
  • FHIRResourceToString (8-16)
  • defaultHasMinimumData (3-3)
packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
  • formatIdentifiers (5-19)
packages/core/src/external/fhir/export/string/shared/deny.ts (1)
  • emptyIfDenied (9-15)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
  • formatCodeableConcepts (78-96)
packages/core/src/external/fhir/export/string/shared/period.ts (1)
  • formatPeriod (11-25)
packages/core/src/external/fhir/export/string/shared/reference.ts (1)
  • formatReferences (8-26)
packages/core/src/external/fhir/resources/diagnostic-report.ts (1)
  • presentedFormsToText (6-14)
packages/core/src/external/fhir/export/string/shared/narrative.ts (1)
  • formatNarrative (10-28)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/resources/allergy-intolerance.ts (6)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
  • FHIRResourceToString (8-16)
  • defaultHasMinimumData (3-3)
packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
  • formatIdentifiers (5-19)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)
  • formatCodeableConcept (18-68)
  • formatCodeableConcepts (78-96)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/shared/reference.ts (1)
  • formatReference (28-41)
packages/core/src/external/fhir/export/string/shared/annotation.ts (1)
  • formatAnnotations (5-21)
packages/core/src/external/fhir/export/string/resources/organization.ts (6)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (1)
  • FHIRResourceToString (8-16)
packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
  • formatNpiIdentifiers (52-58)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/shared/telecom.ts (1)
  • formatTelecoms (12-27)
packages/core/src/external/fhir/export/string/shared/address.ts (1)
  • formatAddresses (11-27)
packages/core/src/external/fhir/export/string/shared/coding.ts (1)
  • formatCodings (16-34)
packages/core/src/external/fhir/export/string/shared/address.ts (2)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
  • defaultIsDebug (1-1)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/utils/src/open-search/semantic-ingest.ts (5)
packages/shared/src/index.ts (1)
  • sleep (13-13)
packages/utils/src/shared/sentry.ts (1)
  • initSentry (15-23)
packages/core/src/command/patient-loader-metriport-api.ts (1)
  • getDomainFromDTO (112-141)
packages/core/src/command/consolidated/search/fhir-resource/ingest-lexical.ts (1)
  • ingestLexical (21-53)
packages/core/src/external/opensearch/shared/bulk.ts (1)
  • BulkResponseErrorItem (17-23)
packages/api/src/routes/ehr/eclinicalworks/auth/middleware.ts (3)
packages/api/src/domain/jwt-token.ts (1)
  • JwtTokenData (21-21)
packages/api/src/routes/ehr/shared.ts (3)
  • ParseResponse (17-20)
  • processPatientRoute (91-100)
  • processDocumentRoute (102-111)
packages/shared/src/interface/external/ehr/eclinicalworks/jwt-token.ts (1)
  • eclinicalworksDashSource (4-4)
packages/core/src/external/fhir/export/string/shared/__tests__/codeable-concept.test.ts (1)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
  • formatCodeableConcept (18-68)
packages/core/src/external/fhir/export/string/resources/medication-request.ts (11)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
  • FHIRResourceToString (8-16)
  • defaultHasMinimumData (3-3)
packages/core/src/external/fhir/export/string/shared/identifier.ts (2)
  • formatIdentifiers (5-19)
  • formatIdentifier (30-44)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)
  • formatCodeableConcept (18-68)
  • formatCodeableConcepts (78-96)
packages/core/src/external/fhir/export/string/shared/reference.ts (2)
  • formatReference (28-41)
  • formatReferences (8-26)
packages/core/src/external/fhir/export/string/shared/annotation.ts (1)
  • formatAnnotations (5-21)
packages/core/src/external/fhir/export/string/shared/dosage.ts (1)
  • formatDosages (10-24)
packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
  • formatQuantity (11-24)
packages/core/src/external/fhir/export/string/shared/duration.ts (1)
  • formatDuration (7-25)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/shared/period.ts (1)
  • formatPeriod (11-25)
packages/core/src/external/fhir/export/string/shared/narrative.ts (1)
  • formatNarrative (10-28)
packages/core/src/external/fhir/export/string/shared/dosage.ts (7)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
  • defaultIsDebug (1-1)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/shared/timing.ts (1)
  • formatTiming (11-35)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
  • formatCodeableConcept (18-68)
packages/core/src/external/fhir/export/string/shared/range.ts (1)
  • formatRange (10-33)
packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
  • formatQuantity (11-24)
packages/core/src/external/fhir/export/string/shared/ratio.ts (1)
  • formatRatio (10-37)
packages/core/src/external/fhir/export/string/shared/coding.ts (3)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/shared/deny.ts (2)
  • isAllowedSystem (18-20)
  • emptyIfDenied (9-15)
packages/core/src/external/fhir/export/string/shared/code-display.ts (1)
  • codeAndDisplayToString (3-11)
packages/core/src/external/fhir/export/string/shared/timing.ts (8)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
  • defaultIsDebug (1-1)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
  • formatCodeableConcept (18-68)
packages/core/src/external/fhir/export/string/shared/duration.ts (1)
  • formatDuration (7-25)
packages/core/src/external/fhir/export/string/shared/range.ts (1)
  • formatRange (10-33)
packages/core/src/external/fhir/export/string/shared/period.ts (1)
  • formatPeriod (11-25)
packages/core/src/external/fhir/export/string/shared/numeric.ts (2)
  • formatNumericWithMax (18-39)
  • formatNumeric (1-16)
packages/core/src/external/fhir/export/string/shared/string.ts (1)
  • formatStrings (3-15)
packages/core/src/external/fhir/export/string/shared/telecom.ts (2)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
  • defaultIsDebug (1-1)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
  • FIELD_SEPARATOR (4-4)
packages/core/src/command/ai-brief/filter.ts (2)
packages/api/src/routes/medical/schemas/fhir.ts (1)
  • Bundle (23-23)
packages/core/src/domain/ai-brief/modify-resources.ts (1)
  • SlimResource (63-77)
packages/core/src/external/opensearch/index-based-on-file.ts (2)
packages/core/src/external/opensearch/index-based-on-resource.ts (2)
  • IndexFields (3-9)
  • SearchResult (19-19)
packages/core/src/external/opensearch/index.ts (1)
  • contentFieldName (1-1)
🪛 Biome (1.9.4)
packages/core/src/external/fhir/export/string/resources/coverage.ts

[error] 107-118: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/core/src/external/opensearch/lexical/lexical-search.ts

[error] 15-15: Use a regular expression literal instead of the RegExp constructor.

Regular expression literals avoid some escaping required in a string literal, and are easier to analyze statically.
Safe fix: Use a literal notation instead.

(lint/complexity/useRegexLiterals)

packages/core/src/external/html/remove-tags.ts

[error] 52-52: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/core/src/external/fhir/export/string/shared/dosage.ts

[error] 45-45: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (223)
packages/core/src/external/opensearch/file/file-remover-direct.ts (1)

2-2: Import path change looks good.

The updated import path correctly reflects the new directory structure where OpenSearch file handling modules have been organized into a file/ subdirectory.

packages/core/src/external/html/remove-tags.ts (1)

41-91: Well-structured HTML tag removal utility.

This is a comprehensive and well-designed utility function that follows coding guidelines. The step-by-step regex processing approach makes it maintainable and debuggable.

🧰 Tools
🪛 Biome (1.9.4)

[error] 52-52: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/api/src/command/hie/unlink-patient-from-organization.ts (1)

14-14: Import path update aligns with directory restructuring.

The updated import path correctly reflects the new OpenSearch module organization with the file/ subdirectory. This change is consistent with the broader restructuring of OpenSearch-related modules.

packages/api/src/command/medical/patient/consolidated-delete.ts (1)

17-17: LGTM! Good architectural improvement.

The import path change centralizes the consolidated patient data retrieval logic in the core package, which promotes code reuse and follows the Onion Pattern architecture. This aligns well with the broader refactoring effort to move shared functionality to the core package.

packages/utils/src/open-search/re-populate.ts (1)

6-6: LGTM! Import path update for module restructuring.

The import path update to include the additional file/ directory segment aligns with the broader restructuring of OpenSearch-related modules. This maintains consistency across the codebase while organizing file ingestor functionality into a more structured directory hierarchy.

packages/infra/lib/api-stack/ccda-search-connector.ts (1)

112-112: LGTM! Improved URL formatting with explicit HTTPS scheme.

The addition of the "https://" prefix to the search host environment variable ensures proper URL formatting and explicit HTTPS usage. This improvement promotes consistency across the stack and prevents potential issues with missing protocol schemes in endpoint URLs.

packages/utils/src/open-search/cleanup.ts (1)

3-5: LGTM! Consistent import path update for module restructuring.

The import path update mirrors the changes in other OpenSearch-related files, maintaining consistency across the codebase. This is part of the broader restructuring effort to organize OpenSearch file ingestor functionality into a more structured directory hierarchy.

packages/core/src/external/fhir/export/string/shared/debug.ts (1)

1-1: LGTM! Clean centralized debug configuration.

The constant follows naming conventions and provides a centralized default for debug mode across FHIR string conversion utilities.

packages/core/src/external/ehr/bundle/job/create-resource-diff-bundles/steps/compute/ehr-compute-resource-diff-bundles-local.ts (2)

4-4: LGTM! Import updated consistently with function refactoring.

The import correctly reflects the new getConsolidatedFile function from the consolidated data retrieval refactoring.


149-149: LGTM! Function call updated to match new API.

The call to getConsolidatedFile is consistent with the updated import and maintains the same functionality based on the provided context.

packages/lambdas/src/shared/ehr.ts (1)

37-37: Good fix! Error message now correctly identifies the invalid field.

The error message was previously incorrectly stating "Invalid patientId" when validating departmentId. This fix improves error clarity and debugging.

packages/core/src/external/opensearch/file/file-ingestor-sqs.ts (1)

4-8: LGTM! Import paths updated consistently for directory restructuring.

The import path adjustments correctly reflect the OpenSearch module reorganization with consistent depth changes across all imports.

packages/api/src/routes/internal/jwt-token/index.ts (1)

4-4: LGTM! Clean integration following established patterns.

The new EClinicalWorks route registration follows the existing pattern perfectly, with alphabetical ordering maintained for both imports and route registrations.

Also applies to: 15-15

packages/core/src/util/config.ts (1)

65-67: LGTM! Consistent with existing configuration pattern.

The new getLexicalSearchIndexName() method follows the established pattern used by other configuration getters in this class, using getEnvVarOrFail for required environment variables and maintaining consistent naming conventions.

packages/lambdas/src/sqs-to-opensearch-xml.ts (1)

2-3: LGTM! Import path updates align with module reorganization.

The updated import paths correctly reflect the refactoring that moved OpenSearch file ingestor modules into a file/ subdirectory structure.

packages/utils/src/open-search/semantic-search.ts (1)

6-6: LGTM! Import path correctly updated for consolidated module structure.

The updated import path reflects the move of semantic search functionality from external OpenSearch modules to the consolidated command structure, aligning with the broader refactoring effort to centralize search operations.

packages/api/src/external/ehr/shared/utils/bundle/functions.ts (1)

53-53: LGTM! Consistent EHR integration pattern.

The addition of EClinicalWorks to the bundle functions mapping follows the established pattern for EHR sources that don't yet have bundle functionality implemented. The undefined value ensures proper error handling through the getBundleFunctions function.

packages/shared/src/interface/external/ehr/eclinicalworks/index.ts (1)

1-1: LGTM! Standard module export pattern.

The re-export pattern correctly centralizes JWT token exports for EClinicalWorks, following TypeScript best practices for module organization.

packages/api/src/routes/medical/document.ts (1)

4-4:

✅ Verification successful

Verify the new import path exists and functions correctly.

The import path change aligns with the search functionality consolidation. Please ensure the searchDocuments function is properly exported from the new consolidated module location.


🏁 Script executed:

#!/bin/bash
# Verify that the searchDocuments function exists at the new import path
ast-grep --pattern 'export { searchDocuments }' 
ast-grep --pattern 'export const searchDocuments'
ast-grep --pattern 'export function searchDocuments'

Length of output: 156


🏁 Script executed:

#!/bin/bash
set -e
# Locate the document-reference search module directory under core/command/consolidated
dirs=$(fd -t d 'packages/core/command/consolidated/search/document-reference')
echo "Found directory(s):"
echo "$dirs"

# For each found directory, list its files and search for searchDocuments
for d in $dirs; do
  echo "---- Files in $d ----"
  find "$d" -maxdepth 1 -type f -print
  echo "---- Grep for searchDocuments in $d ----"
  rg 'searchDocuments' "$d" || true
done

Length of output: 148


🏁 Script executed:

#!/bin/bash
set -e
echo "🔍 Searching for definitions of 'searchDocuments' in TypeScript files"
rg -nE 'export\s+(?:const|function)\s+searchDocuments' -g '*.ts' || true

echo -e "\n🔄 Searching for any re-exports of 'searchDocuments'"
rg -n 'export\s*{[^}]*searchDocuments' -g '*.ts' || true

echo -e "\n📁 Listing all 'document-reference' directories"
fd -t d document-reference || true

Length of output: 1154


🏁 Script executed:

#!/bin/bash
set -e

base="packages/core/src/command/consolidated/search/document-reference"

echo "📂 Listing all files under $base:"
find "$base" -type f -print

echo -e "\n🔍 Searching for any occurrence of 'searchDocuments' in the above files:"
rg -n "searchDocuments" "$base" || true

Length of output: 1003


Import Path Verified: searchDocuments Export Exists

The searchDocuments function is indeed exported from
packages/core/src/command/consolidated/search/document-reference/search.ts (see line 27), so the import

import { searchDocuments } from "@metriport/core/command/consolidated/search/document-reference/search";

is valid. No further changes needed.

packages/api/src/external/cda/generate-ccd.ts (2)

18-18: LGTM! Import reordering is fine.

The reordering of the normalizeBundle import doesn't affect functionality and maintains the same relative path.


2-2:

✅ Verification successful

Verify the consolidated import path and approve the refactoring.

The import path change to the consolidated module aligns with the broader refactoring effort. Please ensure the function is properly exported from the new location.


🏁 Script executed:

#!/bin/bash
# Verify that getConsolidatedPatientData is exported from the consolidated module
ast-grep --pattern 'export { getConsolidatedPatientData }'
ast-grep --pattern 'export const getConsolidatedPatientData'
ast-grep --pattern 'export function getConsolidatedPatientData'

Length of output: 189


Let’s locate the consolidated-get module and inspect its exports to confirm that getConsolidatedPatientData is indeed exposed:


🏁 Script executed:

#!/bin/bash
# 1. List all files named consolidated-get*.ts to find the module
echo "=== Finding consolidated-get files ==="
fd "consolidated-get" -e ts -t f

# 2. Search for any definition or export of getConsolidatedPatientData within the core package
echo -e "\n=== Searching for getConsolidatedPatientData references ==="
rg -n "getConsolidatedPatientData" packages/core

# 3. For each consolidated-get file found, print the first 200 lines to inspect exports
echo -e "\n=== Inspecting module exports ==="
for f in $(fd "consolidated-get" -e ts -t f); do
  echo -e "\n---- $f ----"
  sed -n '1,200p' "$f"
done

Length of output: 22081


✅ Confirmed: getConsolidatedPatientData export exists in core module and the new import path is valid.
No further changes required.

packages/infra/lib/api-stack.ts (1)

583-583: LGTM! Explicit HTTPS prefix improves security and clarity.

Adding the explicit "https://" prefix removes protocol ambiguity and ensures secure communication with the search endpoint. This is a good security practice that aligns with the infrastructure updates mentioned in the summary.

packages/infra/config/env-config.ts (1)

270-272: LGTM! Consistent configuration pattern.

The addition of EClinicalWorks configuration follows the established pattern used by other EHR integrations, with the env field properly typed as a string. The integration fits well within the existing ehrIntegration structure.

packages/api/src/errors/index.ts (1)

10-12: Good deprecation practice.

The JSDoc deprecation comment properly guides developers to use the centralized error handling utility while maintaining backward compatibility. This supports the gradual migration to shared utilities.

packages/shared/src/interface/external/ehr/source.ts (1)

6-6: LGTM! Consistent enum addition.

The addition of eclinicalworks follows the established naming convention and automatically extends the derived types and arrays. The implementation maintains consistency with existing EHR sources.

packages/api/src/external/ehr/shared/utils/mappings.ts (1)

27-27: LGTM! Consistent mapping pattern.

The addition of EClinicalWorks to the schema map with undefined follows the same pattern as Canvas, maintaining type safety while indicating no secondary mappings are currently defined for this EHR source.

packages/core/src/external/opensearch/file/file-search-connector-factory.ts (2)

8-8: LGTM! Import path updated for directory restructuring.

The import path correctly reflects the new directory structure after the OpenSearch module reorganization.


34-34:

✅ Verification successful

Verify that Config.getSearchEndpoint() returns complete URLs.

The removal of the "https://" + prefix suggests that Config.getSearchEndpoint() now returns complete URLs including the protocol. Please verify this assumption is correct and consistent across the codebase.

Also applies to: 49-49


🏁 Script executed:

#!/bin/bash
# Description: Verify that Config.getSearchEndpoint() returns complete URLs with protocol
# Expected: All usages should be consistent with the new pattern

echo "=== Searching for Config.getSearchEndpoint() usage ==="
rg -A 2 -B 2 "Config\.getSearchEndpoint\(\)"

echo -e "\n=== Searching for https:// + endpoint patterns ==="
rg -A 2 -B 2 "https.*endpoint|endpoint.*https"

echo -e "\n=== Checking Config class implementation ==="
ast-grep --pattern 'static getSearchEndpoint(): string {
  $$$
}'

Length of output: 31251


Here’s a script to locate where getSearchEndpoint is defined and inspect its body:


🏁 Script executed:

#!/bin/bash
echo "=== Locate getSearchEndpoint references ==="
rg -n "getSearchEndpoint" -R "packages/core/src"

echo -e "\n=== Locate Config class definition ==="
rg -n "class Config" -R "packages/core/src"

Length of output: 1090


Let’s correct the ripgrep usage and pull in some context around the method definition:


🏁 Script executed:

#!/bin/bash
echo "=== Locating getSearchEndpoint method definition ==="
rg -n -C 5 "static getSearchEndpoint" packages/core/src

echo -e "\n=== Locating Config class declaration ==="
rg -n -C 5 "class Config" packages/core/src

Length of output: 1778


Ensure SEARCH_ENDPOINT includes the protocol
Config.getSearchEndpoint() simply returns the raw SEARCH_ENDPOINT env var (packages/core/src/util/config.ts:49–51), so the removed https:// prefix means your deployments and CI/CD must now set SEARCH_ENDPOINT to a full URL (e.g. https://search.example.com).

• packages/core/src/util/config.ts – getSearchEndpoint returns getEnvVarOrFail("SEARCH_ENDPOINT") without adding https://
• Verify all environment configurations, README or deployment scripts now supply https://… in SEARCH_ENDPOINT

No code changes needed; just confirm all configs have been updated.

packages/core/src/external/aws/document-signing/bulk-sign.ts (1)

11-11: LGTM! Import path updated for consolidated architecture.

The import path change aligns with the broader refactoring to consolidate search functionality under the unified command structure. The function interface remains the same, ensuring backward compatibility.

packages/core/src/external/opensearch/shared/id.ts (1)

1-12: LGTM! Clean utility function with good documentation.

The getEntryId function implementation is correct and well-documented. The concatenation approach using underscores creates unique identifiers as intended.

packages/core/src/command/consolidated/get-snapshot.ts (1)

7-7: LGTM! Explicit type definition improves clarity.

Making the undefined type explicit in the optional property is a good TypeScript practice that enhances code clarity and aligns with strict typing standards.

packages/api/src/external/carequality/document/process-outbound-document-retrieval-resps.ts (2)

11-11: LGTM! Import path updated for consolidated architecture.

The import path change from relative ../../aws/opensearch to the consolidated module @metriport/core/command/consolidated/search/document-reference/ingest aligns with the architectural refactoring effort.


303-303: LGTM! Function call updated to match new signature.

The change from passing the full mergedFHIRDocRef object to just mergedFHIRDocRef.id correctly aligns with the updated ingestIntoSearchEngine function signature, which now expects an entryId: string as the second parameter instead of a complete document reference object.

packages/core/src/command/consolidated/snapshot-on-s3.ts (1)

35-35: LGTM! Type annotation improvement.

Making the optional nature of requestId explicit with string | undefined is a good TypeScript practice that improves type safety and clarity.

packages/core/src/domain/ai-brief/modify-resources.ts (2)

56-56: LGTM! Useful 3D11 addition to cleanup patterns.

Adding "<content/>" to the removal list enhances the note cleanup functionality for better text processing.


591-591: LGTM! Good refactoring for reusability.

Exporting cleanUpNote enables its reuse across other modules, which follows the DRY principle and improves modularity.

packages/api/src/routes/ehr/index.ts (2)

11-12: LGTM! Consistent import pattern.

The import statements follow the established pattern for EHR integrations with clear naming conventions.


32-32: LGTM! Proper route registration.

The route registration follows the established middleware chain pattern used by other EHR integrations, ensuring consistent authentication and access control.

packages/core/src/external/fhir/__tests__/bundle.ts (1)

22-27: LGTM! Enhanced FHIR bundle compliance.

Adding the total property when entries are present makes the test bundles more realistic and compliant with FHIR standards. The conditional logic ensures proper bundle structure.

packages/core/src/external/opensearch/shared/filters.ts (1)

1-3: LGTM! Clean utility function implementation.

This utility function correctly creates OpenSearch filter objects for patient identification. The implementation is simple, well-typed, and follows the coding guidelines. The function name is descriptive and uses proper camelCase naming.

packages/api/src/external/commonwell/document/document-query.ts (2)

38-38: Good refactoring: Moving to absolute package import.

The change from a relative import to an absolute package import improves modularity and aligns with the broader restructuring of OpenSearch functionality mentioned in the AI summary.


711-711:

✅ Verification successful

Verify the function signature change is correct.

The function call has been modified to pass fhirDocRef.id instead of the entire fhirDocRef object. While the AI summary indicates this aligns with similar changes in related files, please ensure that the ingestIntoSearchEngine function signature expects a document reference ID as the first parameter.


🏁 Script executed:

#!/bin/bash
# Description: Verify the function signature of ingestIntoSearchEngine to confirm it expects a document reference ID

# Search for the function definition
ast-grep --pattern $'export function ingestIntoSearchEngine($_, $$$) {
  $$$
}'

# Also search for function declarations/interfaces
rg -A 10 "ingestIntoSearchEngine.*function|function.*ingestIntoSearchEngine"

Length of output: 1261


🏁 Script executed:

#!/bin/bash
rg -n "ingestIntoSearchEngine" -A5 -B5 packages/api/src/external/commonwell/document/document-query.ts

Length of output: 1330


Confirmed matching signature—no change needed

The ingestIntoSearchEngine function in
packages/core/src/command/consolidated/search/document-reference/ingest.ts
is declared as:

export async function ingestIntoSearchEngine(
  patient: Pick<Patient,"id"|"cxId">,
  entryId: string,       // <— expects a string ID here
  file: { key:string; bucket:string; contentType?:string },
  requestId: string,
  log = out(`ingestIntoSearchEngine`).log
): Promise<void> {  }

And in
packages/api/src/external/commonwell/document/document-query.ts
you now correctly pass fhirDocRef.id (a string) as the entryId argument.

No further updates required.

packages/core/src/external/fhir/consolidated/consolidated.ts (1)

18-18: Good type clarification improvement.

The explicit inclusion of undefined in the type annotation improves clarity, even though optional properties already include undefined by default in TypeScript. This change enhances code readability and aligns with similar explicit typing improvements mentioned in the AI summary.

packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-factory.ts (1)

5-6: Factory function implementation looks good.

The function correctly implements the factory pattern, follows naming conventions, and returns the appropriate interface type. The current implementation provides a working solution while allowing for future extensibility.

packages/core/src/external/fhir/codeable-concept.ts (1)

44-45: LGTM! Improved type safety and defensive programming.

The parameter type change to accept string | undefined and the early guard clause improve the function's robustness by handling falsy inputs gracefully. This prevents potential runtime errors and makes the function more defensive.

packages/infra/lib/api-stack/api-service.ts (2)

335-336: Environment variable addition for lexical search with migration note.

The addition of LEXICAL_SEARCH_INDEX follows the established pattern. The TODO comment indicates this is temporary until lambda functions handle lexical search functionality.


365-365: EClinicalWorks environment variable integration.

The addition of EHR_ECLINICALWORKS_ENVIRONMENT properly integrates the new EClinicalWorks EHR support into the API service environment configuration.

packages/core/src/external/fhir/export/string/shared/age.ts (1)

1-18: Well-implemented FHIR Age formatting utility.

The implementation correctly treats Age as a special case of Quantity and delegates to the existing formatQuantity function. The function follows the established patterns in the codebase:

  • Consistent parameter destructuring with other formatting utilities
  • Proper TypeScript typing with FHIR types
  • Clear JSDoc documentation explaining the Age-Quantity relationship
  • Functional programming style with single responsibility
packages/api/src/external/ehr/shared/utils/jwt-token.ts (3)

15-18: Proper import integration for EClinicalWorks JWT tokens.

The import follows the established pattern for other EHR providers, maintaining consistency in the codebase structure.


37-37: Consistent addition to JWT token sources array.

Adding eclinicalworksDashSource to the ehrDashJwtTokenSources array follows the same pattern used for other EHR providers, ensuring proper recognition of EClinicalWorks tokens.


48-49: Proper union type extension for EClinicalWorks.

The addition of EClinicalWorksDashJwtTokenData to the EhrDashJwtTokenData union type correctly extends type safety to cover EClinicalWorks JWT tokens, maintaining consistency with the existing pattern.

packages/core/src/external/fhir/export/string/shared/code-display.ts (1)

3-11: LGTM! Well-implemented utility function.

The function logic correctly handles all combinations of code and display presence, uses proper early returns, and follows functional programming principles. The implementation is clean and deterministic.

packages/core/src/external/fhir/export/string/shared/string.ts (1)

3-15: LGTM! Excellent adherence to coding guidelines.

The function properly uses destructured parameters, implements early returns, and follows functional programming principles. The debug labeling logic is clear and the TypeScript types are appropriate.

packages/core/src/command/consolidated/consolidated-filter.ts (5)

2-2: LGTM: Appropriate import for timing measurement.

The addition of elapsedTimeFromNow import supports the new timing measurement functionality added later in the file.


18-18: LGTM: Function name clarification.

The rename from getConsolidated to getConsolidatedFile provides better clarity about what the function returns and aligns with the updated function signature shown in the relevant code snippets.


60-60: LGTM: Consistent usage of renamed function.

The function call correctly uses the renamed getConsolidatedFile function, maintaining consistency with the import change.


97-103: LGTM: Excellent addition of timing measurement and logging.

The timing measurement provides valuable observability for performance monitoring of the addMissingReferencesFn operation. The implementation correctly uses the imported elapsedTimeFromNow utility and provides clear, informative logging.


120-125: LGTM: Improved bundle integrity with correct total field.

This refactoring ensures that the total field accurately reflects the number of entries in the bundle after adding missing references. Creating the newEntries array first and then assigning both total and entry fields ensures consistency and maintains FHIR bundle integrity.

packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)

3-3: LGTM: Well-defined default constant.

The defaultHasMinimumData cons F438 tant provides a clear default value for tracking whether resources contain sufficient data for string representation. The false default is conservative and appropriate.


12-15: LGTM: Backward-compatible interface enhancement.

The addition of the optional isDebug parameter to the toString method enhances the interface while maintaining backward compatibility. The updated JSDoc clearly documents the parameter's purpose for including debug information like property labels.

packages/core/src/external/opensearch/file/file-ingestor.ts (3)

1-2: LGTM: Configuration type standardization.

The import changes standardize the use of OpenSearchConfig from the parent directory and update the IndexFields import path. This aligns with the broader OpenSearch module refactoring mentioned in the AI summary.


10-10: LGTM: Consistent type alias update.

The type alias correctly uses the standardized OpenSearchConfig type, maintaining consistency with the import changes.


17-17: LGTM: Type clarification improves code readability.

Making the contentType parameter type more explicit as string | undefined rather than just optional string improves code clarity without changing the method's logic or behavior.

packages/core/src/external/opensearch/shared/delete.ts (1)

1-14: LGTM: Clean and focused delete query utility.

This new module provides a well-structured utility for creating OpenSearch delete queries. The implementation demonstrates good practices:

  • Clear type definition: DeleteParams clearly defines the required parameters
  • Reusability: Leverages the existing getPatientFilters function from the shared filters module
  • Proper structure: Returns a correctly formatted OpenSearch bool query with must clauses
  • Focused responsibility: Single-purpose module that does one thing well

The integration with getPatientFilters ensures consistency with other query construction patterns in the codebase.

packages/shared/src/interface/external/ehr/eclinicalworks/jwt-token.ts (1)

1-10: LGTM! Clean zod schema implementation.

The JWT token schema is well-structured and follows TypeScript best practices. The use of z.literal() for source validation ensures type safety, and the naming conventions align with the coding guidelines.

packages/api/src/command/jwt-token.ts (1)

55-70: LGTM! Well-implemented ID-based JWT token retrieval functions.

The new functions getJwtTokenById and getJwtTokenByIdOrFail follow the established patterns in this module perfectly:

  • Consistent naming conventions and documentation
  • Proper error handling with NotFoundError
  • Clear indication that expiration is not checked
  • Good TypeScript usage with proper return types

The implementation aligns well with the existing codebase structure and coding guidelines.

packages/core/src/external/opensearch/file/file-searcher.ts (1)

1-12: LGTM! Clean and well-designed interface.

The OpenSearchFileSearcher interface and SearchRequest type are well-structured:

  • Clear separation of concerns with focused interface
  • Good documentation referencing Elasticsearch query syntax
  • Proper TypeScript typing with meaningful names
  • Follows functional programming principles with clear input/output contract

The design aligns with the coding guidelines for minimizing coupling and building deterministic functions.

packages/core/src/external/opensearch/index-based-on-file.ts (1)

1-12: LGTM! Well-structured type definitions with good architectural consistency.

The type definitions follow the established pattern from index-based-on-resource.ts while being appropriately adapted for file-based indexing. The use of computed property names for the content field and the proper omission of sensitive content from search results demonstrates good design practices.

packages/core/src/util/error/shared.ts (1)

62-67: Consider consistent parameter naming.

The returned function uses error as the parameter name, which is more descriptive than err used in some deprecated functions above. This follows the coding guidelines for meaningful naming.

packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts (1)

1-15: LGTM! Clean and well-designed interface.

The type definitions and interface follow TypeScript best practices with meaningful naming, appropriate use of optional properties, and proper destructuring in the method signature. The interface design is clean and follows the coding guidelines for functional programming style with clear input/output types.

packages/api/src/shared/config.ts (1)

335-337: LGTM! Consistent implementation following established patterns.

The new getEClinicalWorksEnv() method follows the same pattern as other EHR environment getters in the class. Using getEnvVar() instead of getEnvVarOrFail() appropriately indicates this is optional configuration, consistent with other EHR integrations.

packages/api/src/routes/ehr/eclinicalworks/routes/dash.ts (3)

1-13: LGTM! Well-structured imports following coding guidelines.

The imports follow the coding guidelines with kebab-case file names and meaningful import organization. The structure is clean and follows TypeScript best practices.


28-37: Good use of skip paths for document downloads.

The implementation correctly uses skip paths for document download URLs, allowing these endpoints to bypass patient ID checks when appropriate. The middleware chain is well-structured.


20-27:

✅ Verification successful

Verify middleware execution order for security.

The middleware chain appears correctly ordered with parameter handling, route processing, ID validation, and authorization. However, ensure that the processEhrPatientId middleware properly validates the token-derived patient ID against the request parameters to prevent unauthorized access.


🏁 Script executed:

#!/bin/bash
# Description: Verify the middleware chain and security validations

# Search for processEhrPatientId implementation to understand security checks
ast-grep --pattern 'export function processEhrPatientId($$$) {
  $$$
}'

# Look for ForbiddenError usage to confirm proper authorization
rg -A 3 "ForbiddenError" packages/api/src/routes/ehr/shared.ts

Length of output: 925


Middleware chain and patient ID validation verified

The ordering of handleParams, processPatientRoute, processEhrPatientId, patientAuthorization, and medicalPatient is correct. The processEhrPatientId middleware in packages/api/src/routes/ehr/shared.ts throws a ForbiddenError when the token-derived patient ID does not match the request parameter, ensuring proper security. No changes required.

packages/core/src/external/fhir/export/string/shared/range.ts (3)

6-9: Excellent JSDoc documentation.

The function documentation clearly explains the purpose and structure of a FHIR Range, making the code more maintainable.


10-18: Well-designed function signature following coding guidelines.

The function follows the coding guidelines perfectly:

  • Uses destructured parameters instead of multiple parameters
  • Meaningful parameter names
  • Proper TypeScript typing with undefined handling
  • Default parameter for isDebug using shared constant

19-33: Robust implementation with proper edge case handling.

The function correctly handles:

  • Early return for undefined range
  • Conditional inclusion of low/high values
  • Proper array building and joining
  • Consistent formatting with debug labeling
  • Uses shared separator constant for consistency

The logic is deterministic and follows functional programming principles.

packages/core/src/external/opensearch/shared/log.ts (2)

4-4: Good type definition for log levels.

The OpenSearchLogLevel type clearly defines the available logging levels with meaningful string literals.


6-15: Well-implemented conditional logging with proper type safety.

The function design is excellent:

  • Uses proper TypeScript return type annotation
  • Handles all log levels correctly with conditional logic
  • Maintains consistency with the original logger interface
  • Uses emptyFunction from shared package for no-op behavior
  • Follows functional programming principles

The implementation is deterministic and follows the coding guidelines for preferring const and using meaningful names.

packages/core/src/external/opensearch/index-based-on-resource.ts (3)

3-9: Well-defined IndexFields type with proper resource identifiers.

The type definition correctly uses:

  • Meaningful field names (cxId, patientId, resourceType, resourceId)
  • Dynamic content field using the shared constant
  • Proper TypeScript string typing
  • Consistent with resource-based indexing approach

This aligns well with the coding guidelines for meaningful names and TypeScript usage.


11-17: Correct OpenSearch field type mappings.

The index definition properly maps:

  • ID fields as "keyword" type for exact matching
  • Content field as "text" type for full-text search
  • All fields from IndexFields are covered

This follows OpenSearch best practices for field types based on intended usage.


19-19: Clean SearchResult type definition.

The SearchResult type correctly omits the content field from IndexFields, which makes sense for search results where you typically don't need the full content. This follows TypeScript utility type best practices.

packages/api/src/routes/ehr/shared.ts (2)

25-25: LGTM: Function signature enhancement for token processing.

The addition of the tokenId parameter to the parseExternalId callback enhances the token processing capabilities by providing additional context. This change aligns with the EClinicalWorks JWT token handling improvements mentioned in the PR.


31-32: LGTM: Clean implementation of token ID extraction and usage.

The extraction of tokenId from authInfo.id and its subsequent use in the parseExternalId call is well-implemented. This enhancement provides the necessary token context for the downstream processing while maintaining the existing error handling patterns.

packages/core/src/external/fhir/export/string/resources/location.ts (1)

13-74: LGTM: Well-structured FHIR Location resource converter.

The implementation follows the established patterns from other FHIR resource converters in the codebase. Key strengths:

  • Consistent use of shared formatting functions (formatIdentifiers, formatCodeableConcepts, etc.)
  • Proper debug mode support with conditional labeling
  • Appropriate minimum data validation logic
  • Clean separation of concerns and modular approach

The hasMinimumData tracking ensures meaningful output by requiring at least one of: name, aliases, description, or address to be present.

packages/api/src/external/ehr/eclinicalworks/shared.ts (2)

9-20: LGTM: Solid environment validation with meaningful error handling.

The getEClinicalWorksEnv function provides robust validation with clear error messages. The use of MetriportError with additional context ({ environment }) follows the coding guidelines for error handling.


22-24: LGTM: Clean type extension pattern.

The EClinicalWorksPerPracticeParams type properly extends the base EhrPerPracticeParams with the additional authToken field. This follows good TypeScript practices for type composition.

packages/core/src/external/fhir/export/string/resources/organization.ts (3)

13-13: LGTM: Consistent interface implementation with debug support.

The updated method signature correctly implements the FHIRResourceToString<Organization> interface with the optional isDebug parameter, maintaining consistency with other FHIR resource converters.


16-17: LGTM: Appropriate use of NPI-specific identifier formatting.

Using formatNpiIdentifiers for organizations is appropriate since NPI (National Provider Identifier) is the most relevant identifier type for healthcare organizations.


19-37: LGTM: Consistent debug mode implementation and shared function usage.

The implementation effectively uses shared formatting functions (formatTelecoms, formatAddresses, formatCodings) while providing consistent debug mode support with conditional labeling. This aligns well with the broader FHIR string conversion refactoring effort.

packages/core/src/external/fhir/export/string/shared/__tests__/timing.test.ts (7)

1-3: LGTM! Clean imports and proper test setup.

The imports are correctly structured with external dependency first, followed by the function under test.


5-7: LGTM! Proper edge case testing.

Testing undefined input is essential for robust error handling.


9-14: LGTM! Good test coverage for basic timing events.

The test correctly validates formatting of multiple timing events with proper expected output.


23-35: LGTM! Excellent test coverage for complex repeat rules.

This test validates proper formatting of frequency, period, periodUnit, and dayOfWeek fields in debug mode with correct expected output.


79-101: LGTM! Comprehensive integration test.

This test validates that all timing components (events, repeat rules, and codes) are properly formatted together.


136-163: LGTM! Thorough testing of complex repeat rules.

This test covers all possible repeat rule properties including bounds, counts, durations, frequencies, periods, days, times, when clauses, and offset. The expected output correctly formats all these components.


165-174: LGTM! Good edge case handling.

Testing empty arrays ensures the function handles edge cases gracefully by returning undefined.

packages/core/src/command/consolidated/search/fhir-resource/ingest-semantic.ts (5)

1-8: LGTM! Clean imports with proper organization.

The imports are well-organized with domain imports first, followed by external utilities, and proper destructuring of specific functions.


9-14: LGTM! Excellent documentation.

The JSDoc comment clearly explains the function's purpose and parameters, following documentation best practices.


15-21: LGTM! Function signature follows coding guidelines.

The function properly uses destructuring for parameters as recommended in the coding guidelines, with clear typing.


22-24: LGTM! Proper logging setup and data retrieval.

The logging setup includes context (cx and pt) and the consolidated data retrieval follows the expected pattern.


26-33: LGTM! Good configuration pattern.

The OpenSearchTextIngestor configuration properly uses the Config utility for all required settings, with appropriate log level.

packages/core/src/external/fhir/export/string/shared/narrative.ts (4)

1-4: LGTM! Clean imports and proper dependencies.

The imports are well-organized with external types first, followed by internal utilities.


7-18: LGTM! Excellent function documentation and signature.

The JSDoc comment is clear and the function signature follows coding guidelines with proper destructuring and optional parameters.


19-21: LGTM! Proper early returns and edge case handling.

The function correctly handles undefined narratives and empty content after filtering.


22-28: LGTM! Clean conditional formatting logic.

The debug mode implementation is well-structured with clear conditional formatting for both status and content.

packages/core/src/external/fhir/export/string/shared/deny.ts (2)

1-1: LGTM! Good expansion of denied text values.

The addition of "Note" and "History and physical note" to the denied text list makes sense for filtering out non-informative content.


6-9: LGTM! Improved function naming and documentation.

The rename from checkDeny to emptyIfDenied is more descriptive and the JSDoc comment clearly explains the function's behavior.

packages/core/src/external/fhir/export/string/resources/coverage.ts (1)

14-142: LGTM! Well-structured Coverage converter implementation.

The implementation follows excellent patterns:

  • Consistent use of helper functions for formatting
  • Proper debug mode support throughout
  • Appropriate minimum data validation
  • Good separation of concerns with field-specific formatting
  • Proper error handling with early return

The complex nested logic for classes and costs is well-structured and handles edge cases appropriately.

🧰 Tools
🪛 Biome (1.9.4)

[error] 107-118: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

packages/core/src/external/fhir/resources/diagnostic-report.ts (3)

6-14: LGTM! Clean and efficient text extraction.

The presentedFormsToText function correctly uses flatMap to handle the array transformation and filtering in a functional style, which aligns with the coding guidelines.


21-28: LGTM! Proper validation and multi-stage cleanup.

The function correctly:

  • Validates data presence with early return
  • Filters by language (English only) for consistency
  • Applies multi-stage text cleanup for better quality output
  • Uses existing utility functions appropriately

30-33: LGTM! Appropriate additional cleanup.

The HTML tag removal and question mark sequence cleanup provide good additional sanitization of the extracted text.

packages/api/src/routes/internal/jwt-token/eclinicalworks.ts (4)

18-29: LGTM! Clean GET endpoint implementation.

The endpoint correctly:

  • Uses request logging middleware
  • Extracts authorization token properly
  • Delegates to shared utility for consistent token checking
  • Returns appropriate HTTP status and JSON response

31-34: LGTM! Proper request validation schema.

The Zod schema correctly validates the required fields and uses the imported EClinicalWorks-specific schema for type safety.


39-52: LGTM! Well-structured POST endpoint.

The endpoint implementation follows best practices:

  • Proper request validation with Zod
  • Token extraction using shared utility
  • Consistent use of asyncHandler for error handling
  • Appropriate HTTP status response
  • Spread operator usage for clean parameter passing

1-11: LGTM! Proper imports and dependencies.

All imports are well-organized and necessary for the functionality. The use of shared utilities and schemas promotes consistency across the codebase.

packages/core/src/external/opensearch/file/file-searcher-direct.ts (4)

7-7: LGTM! Simplified configuration type.

The direct aliasing of OpenSearchConfigDirectAccess eliminates unnecessary type complexity while maintaining the same interface contract.


51-51: LGTM! Enhanced type safety with generics.

Adding the SearchResult generic parameter to OpenSearchResponse improves type checking and makes the response type more explicit.


57-57: LGTM! Consistent method signature update.

The mapResult method signature correctly reflects the enhanced typing from the response type improvement.


2-5: LGTM! Clean import organization.

The import consolidation improves readability while maintaining all necessary dependencies.

packages/core/src/external/fhir/export/string/shared/period.ts (1)

11-25: LGTM! Well-executed refactoring following established patterns.

The function signature refactoring is excellent and consistent with the broader FHIR string export improvements:

  • Clean object destructuring with meaningful parameter names
  • Proper undefined handling for missing or incomplete period data
  • Conditional debug labeling that maintains backward compatibility
  • Follows TypeScript coding guidelines for parameter destructuring
packages/core/src/external/fhir/export/string/resources/patient.ts (1)

12-29: Excellent refactoring implementation!

The PatientToString class updates perfectly align with the broader FHIR string export improvements:

  • Proper implementation of the updated FHIRResourceToString<Patient> interface
  • Clean object-based parameter passing to formatting functions
  • Appropriate conditional labeling for debug mode
  • Maintains backward compatibility with existing functionality

The code follows TypeScript guidelines well with proper destructuring and meaningful variable names.

packages/core/src/external/fhir/export/string/shared/reference.ts (2)

8-26: LGTM! Clean implementation following best practices.

The formatReferences function correctly implements the object parameter pattern preferred by the coding guidelines and handles edge cases appropriately. The use of flatMap with the nullish coalescing operator ?? [] is an elegant way to filter out undefined formatted references.


28-41: LGTM! Consistent implementation with proper null handling.

The formatReference function follows the same patterns as formatReferences and properly validates the reference display value with trimming and length checks to avoid returning empty strings.

packages/core/src/external/fhir/export/string/resources/communication.ts (1)

12-22: LGTM! Proper class structure and status handling.

The class correctly implements the FHIRResourceToString interface and follows the established pattern for conditional debug labeling.

packages/core/src/external/fhir/export/string/shared/ratio.ts (1)

10-37: LGTM! Consistent implementation following established patterns.

The formatRatio function correctly follows the same object parameter pattern and debug labeling approach used throughout the shared formatting utilities. The logic properly handles undefined ratios and returns undefined when no meaningful parts can be formatted.

packages/utils/src/open-search/semantic-ingest.ts (2)

6-8: LGTM! Clean transition from semantic to lexical ingestion.

The import changes correctly replace the semantic ingestion with lexical ingestion and add the necessary bulk error handling types.


40-44: LGTM! Good error logging setup.

The output folder initialization and file path construction follow good practices for organizing error logs by context and patient ID.

packages/core/src/external/fhir/export/string/shared/quantity.ts (1)

11-24: LGTM: Well-designed API refactoring.

The refactoring to use a single object parameter improves the function's usability and follows the coding guidelines for parameter destructuring. The implementation correctly handles edge cases and maintains backward compatibility through optional parameters.

The logic properly:

  • Returns undefined for falsy values (maintains type safety)
  • Constructs quantity strings without trailing spaces when unit is missing
  • Conditionally includes debug labels
packages/core/src/external/opensearch/lexical/lexical-search.ts (1)

13-60: Well-structured lexical search query builder.

The implementation provides a clean abstraction for building OpenSearch queries with appropriate:

  • Conditional query strategies (match vs simple_query_string)
  • Field exclusions to optimize response size
  • Patient-specific filtering integration

The dual query approach based on the $ prefix provides flexibility for different search scenarios.

🧰 Tools
🪛 Biome (1.9.4)

[error] 15-15: Use a regular expression literal instead of the RegExp constructor.

Regular expression literals avoid some escaping required in a string literal, and are easier to analyze statically.
Safe fix: Use a literal notation instead.

(lint/complexity/useRegexLiterals)

packages/core/src/external/fhir/export/string/shared/duration.ts (1)

7-25: Consistent and well-implemented duration formatter.

The implementation follows the established pattern for FHIR formatting utilities with:

  • Object parameter destructuring (following guidelines)
  • Proper undefined handling
  • Consistent debug labeling approach
  • Clean string construction logic
packages/api/src/external/ehr/shared/utils/client.ts (1)

3-3: LGTM: Clean extension of EHR client types.

The changes properly extend the type system to support new EHR providers:

  • Added imports for EClinicalWorksEnv and HealthieEnv
  • Extended EhrEnv union type consistently
  • Renamed EhrClient to EhrClientTwoLeggedAuth for better clarity about authentication type
  • Updated generic constraints accordingly

The modifications maintain backward compatibility while enabling support for additional EHR systems.

Also applies to: 5-5, 13-13, 25-25, 57-57

packages/api/src/routes/medical/patient.ts (2)

3-4: LGTM! Centralized imports improve modularity.

The imports align with the centralization effort mentioned in the PR objectives, moving logic from local implementations to shared core modules.


201-201:

✅ Verification successful

Verify backward compatibility of the simplified search implementation.

The new implementation using makeSearchConsolidated().search({ patient, query }) is much simpler than the previous conditional logic. Please ensure this maintains the same search functionality and API response format.


🏁 Script executed:

#!/bin/bash
# Description: Check if there are any breaking changes in the search response format
# Expected: Consistent response structure between old and new implementations

# Look for any response format definitions or types
rg -A 5 -B 5 "search.*response|SearchResponse|SearchResult" packages/core/src/command/consolidated/search/

# Check for any migration notes or compatibility considerations
rg -A 3 -B 3 "backward.*compatible|breaking.*change|migration" packages/core/src/command/consolidated/search/

Length of output: 10786


🏁 Script executed:

#!/bin/bash
# Locate and inspect the definition of `makeSearchConsolidated` to verify its return type
rg -n -A10 -B10 "makeSearchConsolidated" packages/api

Length of output: 3429


🏁 Script executed:

#!/bin/bash
# Inspect the factory for consolidated search to verify its behavior and return types
rg -n -A50 -B5 "export function makeSearchConsolidated" -A50 packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-factory.ts

Length of output: 588


🏁 Script executed:

#!/bin/bash
# Inspect the SearchConsolidatedDirect implementation to verify `search` behavior and return type
sed -n '1,200p' packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-direct.ts

# Inspect the SearchConsolidated interface/type definition
sed -n '1,200p' packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts

Length of output: 3536


No backward‐compatibility issues detected

  • makeSearchConsolidated() still returns SearchConsolidatedDirect, which mirrors the old conditional logic (searchLexical if query is set; getConsolidatedPatientData otherwise).
  • The search() method continues to return the same SearchConsolidatedResult shape ({ url?: string; resourceCount: number }).
  • The API route now simply forwards that result as JSON with status 200.

I did not find any migration notes or response‐format changes in the consolidated‐search code. The new implementation preserves both behavior and response schema.

packages/core/src/external/fhir/export/string/shared/__tests__/codeable-concept.test.ts (3)

1-13: LGTM! Well-structured imports and constants.

The imports are properly organized and include all necessary dependencies for comprehensive testing.


102-150: Excellent test coverage for text deduplication logic.

These tests comprehensively cover the complex text deduplication scenarios, ensuring the function correctly handles overlapping text and coding display values.


154-173: Helper functions are well-designed.

The getSystem() and makeCodeAndDisplay() functions provide good test data generation with realistic values.

packages/core/src/external/fhir/export/string/resources/related-person.ts (2)

10-16: LGTM! Clean class structure following established patterns.

The class implements the interface correctly and follows the same pattern as other resource converters in the codebase.


28-36: Good use of minimum data tracking for relationship.

The logic correctly identifies relationship as essential data for a RelatedPerson resource and tracks hasMinimumData appropriately.

packages/core/src/external/fhir/export/string/resources/medication-administration.ts (3)

10-18: LGTM! Well-structured class implementing the interface correctly.

The class follows the established pattern and properly initializes the tracking variables.


23-26: Good tracking of minimum data for status.

Correctly identifies status as essential information for a MedicationAdministration resource.


102-116: Comprehensive dosage formatting with proper minimum data tracking.

The dosage formatting logic is well-implemented, handling multiple components and correctly tracking minimum data when dosage information is present.

packages/utils/src/open-search/semantic-text-from-consolidated.ts (3)

34-38: LGTM! Good dual-mode design with proper error handling.

The script elegantly supports both file-based and API-based modes. The environment variable handling is well-structured - using getEnvVar to retrieve variables but deferring validation until needed in API mode.


50-68: Excellent conditional logic structure and error handling.

The dual-mode implementation is well-organized:

  • Clear separation between file and API modes
  • Proper error validation when required environment variables are missing
  • API client instantiation only when needed (good for performance)

76-76: Good improvement to user experience.

Adding the output file path to the console log helps users locate the generated file, which is a nice UX improvement.

packages/api/src/command/medical/patient/consolidated-get.ts (1)

9-11: Excellent refactoring to centralize consolidated data logic.

Moving getConsolidatedPatientData and getConsolidatedPatientDataAsync from local implementations to the core package promotes code reuse and consistency across the platform. The import paths are correct and align with the broader refactoring effort described in the AI summary.

packages/core/src/external/fhir/export/string/resources/practitioner.ts (2)

14-14: Method signature properly updated for debug support.

The method signature correctly implements the updated FHIRResourceToString interface, accepting an optional isDebug parameter and returning string | undefined.


17-54: Excellent modularization with consistent formatting helpers.

The refactoring successfully:

  • Uses dedicated formatting functions (formatNpiIdentifiers, formatHumanNames, etc.) for better maintainability
  • Implements consistent debug mode support with conditional labeling
  • Maintains proper field separation and organization

The helper functions properly handle the isDebug parameter and provide consistent output formatting across FHIR resource converters.

packages/core/src/external/fhir/export/string/resources/medication-dispense.ts (3)

14-16: Good addition of minimum data tracking.

The method signature is properly updated and the hasMinimumData tracking ensures that the method returns undefined when there's insufficient meaningful data, which prevents empty or meaningless string outputs.


32-40: Excellent implementation of minimum data validation.

The medication formatting correctly sets hasMinimumData = true when medication information is present, ensuring that medication dispense records with actual medication data are considered valid for string conversion.


130-136: Good implementation of notes handling with minimum data tracking.

The notes formatting correctly sets hasMinimumData = true when notes are present, and the final check ensures the method returns undefined when no meaningful data is available. This prevents empty medication dispense string representations.

packages/api/src/routes/internal/medical/patient.ts (1)

102-115: Verify routing hierarchy to avoid duplicate /consolidated handlers

Mounting router.use("/consolidated", patientConsolidatedRoutes) adds a new sub-router.
If older /internal/patient/consolidated/* handlers still exist elsewhere, requests may match multiple routes or legacy logic may become unreachable.

Please ensure:

  1. Legacy endpoints have been removed or renamed.
  2. Integration tests cover the new paths.
  3. API documentation is updated.

No code change required, but worth double-checking before release.

packages/core/src/external/opensearch/lexical/lexical-searcher.ts (1)

60-67: Guard against negative or non-integer maxNumberOfResults
Currently only upper/lower bounds are checked. 3.14 or "5" would pass TypeScript compile-time but could break at runtime.
Add Number.isInteger(maxNumberOfResults) and type narrowing to ensure a sane value.

packages/core/src/external/opensearch/file/file-ingestor-direct.ts (1)

91-100: cleanUpContents no longer normalises quotes/newlines – verify search recall
The previous pipeline stripped quotes, newline variants and condensed multiple spaces.
The new implementation delegates to removeHtmlTags then only lower-cases, potentially leaving:

  • Unicode quotation marks ( / )
  • Multiple consecutive spaces
  • Line breaks if isRemoveNewLinesAndSpaces is false

This may fragment the OpenSearch term vector and hurt matching accuracy.
Consider re-adding a lightweight normalisation step:

 const step1 = removeHtmlTags({ contents, log, isTracing });
-const step2 = step1.toLowerCase();
-const lastStepResult = step2;
+const step2 = step1.replace(regexQuotesNewlinesTabs, " ");
+const step3 = step2.replace(regexMultipleSpaces, " ");
+const lastStepResult = step3.toLowerCase();
packages/core/src/external/fhir/export/string/resources/immunization.ts (6)

15-17: LGTM! Clean addition of debug support and minimum data tracking.

The method signature correctly adds the optional isDebug parameter and initializes hasMinimumData with the default value, following the consistent pattern used across other resource converters.


19-19: Good refactoring to parameter object pattern.

The change from formatIdentifiers(immunization.identifier) to formatIdentifiers({ identifiers: immunization.identifier }) follows the new parameter object pattern that improves readability and consistency across formatting functions.


28-36: Excellent implementation of debug support with minimum data tracking.

The vaccine code formatting correctly:

  • Uses the new parameter object pattern with isDebug flag
  • Sets hasMinimumData = true when meaningful data is found
  • Follows consistent labeling conventions

44-46: Verify the intended behavior for primary source display.

The primary source field now displays only the label "Primary Source" without showing the actual boolean value. This might be intentional for privacy/simplicity, but consider if the boolean value should be included in debug mode.

 if (immunization.primarySource) {
-  parts.push(`Primary Source`);
+  parts.push(isDebug ? `Primary Source: ${immunization.primarySource}` : "Primary Source");
 }

57-61: Good update to use emptyIfDenied with minimum data tracking.

The change from checkDeny to emptyIfDenied aligns with the broader refactoring effort, and correctly sets hasMinimumData = true when lot number data is present.


111-112: Proper implementation of minimum data check.

The logic correctly returns undefined when no meaningful data is present, preventing empty or trivial string representations from being returned. This is consistent with the pattern used across other resource converters.

packages/core/src/external/fhir/export/string/bundle-to-string.ts (4)

4-25: Excellent expansion of supported FHIR resource types.

The addition of Communication, Composition, Consent, Coverage, DocumentReference, FamilyMemberHistory, Location, MedicationAdministration, and RelatedPerson significantly broadens the scope of resources that can be converted to text for search and indexing purposes.

Also applies to: 30-51


53-53: Good refinement of resource skipping logic.

Changing from skipping "Patient", "Organization", and "Practitioner" to only skipping "Patient" makes sense since Organization and Practitioner resources can contain valuable searchable information.


131-131: Good addition of debug support to bundleToString.

The optional isDebug parameter enables consistent debug formatting across all resource types, which is valuable for troubleshooting and development.


147-154: Excellent refactoring with proper separation of concerns.

The extraction of resource conversion logic into resourceToString function improves:

  • Code readability and maintainability
  • Testability of individual components
  • Separation of resource support checking from conversion logic
packages/core/src/external/fhir/export/string/resources/consent.ts (4)

1-16: Clean imports and proper type usage.

The imports are well-organized and include all necessary FHIR types and formatting utilities. Good use of specific ConsentProvision types for better type safety.


20-24: Consistent implementation pattern.

The class structure and method signature follow the established pattern from other resource converters, with proper debug support and minimum data tracking initialization.


100-120: Well-structured verification handling.

The verification mapping logic correctly handles the complex structure of ConsentVerification objects, properly filtering and joining components while maintaining debug support.


216-218: Proper minimum data validation and return logic.

The implementation correctly validates minimum data presence and returns undefined when no meaningful data is found, following the established pattern across all resource converters.

packages/core/src/command/consolidated/search/fhir-resource/search-semantic.ts (6)

2-11: Good reorganization of imports with updated paths.

The import path updates reflect a cleaner directory structure, moving from relative paths to more organized external and util directories. The imports are well-organized and include all necessary dependencies.


16-21: Excellent enhancement of JSDoc documentation.

The detailed parameter descriptions including default values and constraints (0 to 10_000 for maxNumberOfResults, 0 to 1 for similarityThreshold) significantly improve the developer experience and API clarity.


75-76: Good use of helper function for bundle construction.

Using buildSearchSetBundle({ entries: sliced }) instead of manual bundle construction improves code maintainability and ensures consistent bundle creation across the codebase.


108-108: Good addition of explicit return type.

Adding the explicit Promise<SearchResult[]> return type improves type safety and makes the function signature more self-documenting.


117-117:

✅ Verification successful

Verify the class name change and its implications.

The change from OpenSearchSemanticSearcherDirect to OpenSearchSemanticSearcher suggests a refactoring of the semantic search implementation. Ensure this class provides the same interface and functionality.


🏁 Script executed:

#!/bin/bash
# Verify the OpenSearchSemanticSearcher class exists and has the expected search method
ast-grep --pattern 'export class OpenSearchSemanticSearcher {
  $$$
  search($$$) {
    $$$
  }
  $$$
}'

Length of output: 106


🏁 Script executed:

#!/bin/bash
set -e

echo "1. Searching for class definitions of OpenSearchSemanticSearcher:"
rg -n "class OpenSearchSemanticSearcher" || echo "No class definition found."

echo
echo "2. Searching for any references to OpenSearchSemanticSearcher in the repo:"
rg -n "OpenSearchSemanticSearcher" || echo "No references found."

echo
echo "3. Inspecting imports in search-semantic.ts (first 50 lines):"
head -n 50 packages/core/src/command/consolidated/search/fhir-resource/search-semantic.ts

Length of output: 3794


🏁 Script executed:

#!/bin/bash
set -e

echo "Inspecting OpenSearchSemanticSearcher class and its methods:"
rg -n 'export class OpenSearchSemanticSearcher' -A 50 packages/core/src/external/opensearch/semantic/semantic-searcher.ts

Length of output: 2019


✅ OpenSearchSemanticSearcher interface verified

Confirmed that the new OpenSearchSemanticSearcher class (packages/core/src/external/opensearch/semantic/semantic-searcher.ts) exports the same constructor signature and async search({…}): Promise<SearchResult[]> method as the previous implementation. No functional or interface changes detected—this refactoring is safe to merge.


41-41:

✅ Verification successful

Verify the function name change is correctly implemented.

The change from getConsolidated to getConsolidatedPatientData should be verified to ensure the new function provides the same functionality and interface.


🏁 Script executed:

#!/bin/bash
# Verify the new getConsolidatedPatientData function exists and has the expected signature
ast-grep --pattern 'export function getConsolidatedPatientData($$$) {
  $$$
}'

Length of output: 80


I wasn’t able to locate the new function declaration with the initial pattern—let’s search more broadly to confirm it exists and how it’s defined.

This will show both imports/usages and the actual declaration (if present). If nothing turns up, we’ll need to verify whether the function was renamed or moved and ensure it’s implemented with the same parameters and return type.


🏁 Script executed:

#!/bin/bash
set -e
echo "All occurrences of getConsolidatedPatientData:"
rg -n "getConsolidatedPatientData" .

echo
echo "Explicit function/export declaration:"
rg -n "export function getConsolidatedPatientData" .

Length of output: 3261


🏁 Script executed:

#!/bin/bash
# Show the declaration of getConsolidatedPatientData to verify its signature
sed -n '80,110p' packages/core/src/command/consolidated/consolidated-get.ts

Length of output: 1223


✅ Function name change verified

The exported getConsolidatedPatientData in
packages/core/src/command/consolidated/consolidated-get.ts
matches the expected signature and return type, and all call sites have been updated:

• Declaration (lines 89–105):

export async function getConsolidatedPatientData({
  patient,
  requestId,
  resources,
  dateFrom,
  dateTo,
  fromDashboard = false,
  forceDataFromFhir = false,
}: GetConsolidatedPatientData): Promise<SearchSetBundle> {  }

• Usages updated in both packages/core and packages/api (e.g. search-lexical.ts, search-semantic.ts, consolidated-delete.ts, routes/medical/patient.ts, etc.)

No further changes required.

packages/core/src/external/fhir/export/string/resources/composition.ts (5)

1-9: LGTM! Well-organized imports with proper grouping.

The imports are cleanly organized with external dependencies first, followed by local utilities grouped by functionality.


13-17: LGTM! Clean class declaration and method signature.

The class properly implements the interface and follows TypeScript best practices with optional parameters and appropriate return types.


60-85: LGTM! Well-structured attestation processing with good error handling.

The attester mapping logic properly handles optional fields and filters out empty values. The implementation correctly follows the functional programming style preferred in the coding guidelines.


115-130: LGTM! Excellent section processing implementation.

The sections mapping logic is well-structured, properly handles nested data, and maintains consistency with the rest of the codebase. The functional approach with filter and map is exemplary.


132-135: LGTM! Proper minimum data validation and return logic.

The hasMinimumData check ensures meaningful output and the final string concatenation is appropriate.

packages/core/src/external/fhir/export/string/resources/document-reference.ts (4)

1-9: LGTM! Consistent import organization.

Imports follow the same clean pattern as the Composition class with proper grouping and naming.


61-76: LGTM! Well-implemented relations processing.

The relatesTo mapping logic properly handles complex nested structures and maintains functional programming principles. Good use of filter and map operations.


107-153: LGTM! Excellent context processing implementation.

The context processing is well-structured with proper separation of concerns, good use of arrays for building context parts, and consistent formatting. The nested structure is handled elegantly.


158-161: LGTM! Consistent minimum data validation.

Follows the same pattern as other resource converters with proper validation and return logic.

packages/core/src/external/fhir/export/string/resources/procedure.ts (4)

2-7: LGTM! Updated imports align with interface changes.

The imports have been properly updated to support the new formatting function signatures and debug functionality.


13-13: LGTM! Method signature updated consistently.

The toString method signature now matches the updated FHIRResourceToString interface with the optional isDebug parameter and appropriate return type.


16-17: LGTM! Consistent use of new formatting function signatures.

The formatting functions are properly called with named parameter objects, which improves readability and maintainability.

Also applies to: 23-27


42-47: LGTM! Proper separation of DateTime and Period formatting.

The separate handling of performedDateTime and performedPeriod is correct and maintains data integrity.

packages/core/src/command/consolidated/search/document-reference/ingest.ts (4)

1-5: LGTM! Improved import organization with relative paths.

The imports have been properly updated to use relative paths, which improves maintainability and follows the project's import conventions.


9-9: LGTM! Simplified function signature and improved logging.

The change from fhirDoc: DocumentReferenceWithId to entryId: string simplifies the interface and reduces coupling. The custom logger follows the coding guidelines preference over console.log.

Also applies to: 16-16


21-21: LGTM! Consistent parameter usage and improved error messaging.

All references to the parameter have been properly updated from document-focused naming to entry-focused naming, which is more accurate for the refactored function signature.

Also applies to: 29-29, 35-36


34-48: LGTM! Proper error handling with structured logging.

The error handling follows coding guidelines with structured error capture and appropriate logging. The decision not to throw errors for search ingestion failures is correctly documented and prevents disruption of main workflows.

packages/core/src/external/fhir/export/string/resources/medication-statement.ts (1)

105-106: Double-check minimum-data semantics

At present, minimum data is satisfied by either a medication (codeable concept or reference) or notes.
If the intention is to always require a medication, regardless of notes, remove the hasMinimumData = true assignment when notes are present, or add an explicit boolean for “hasMedication”.
Confirm the requirement and adjust accordingly.

packages/core/src/external/fhir/export/string/resources/condition.ts (1)

150-176: Minor efficiency: avoid intermediate arrays when concatenating stage / evidence components

components.join(FIELD_SEPARATOR) is fine for a handful of items, but you could short-circuit early if all sub-components are undefined, saving an allocation.

Not blocking—just a minor optimisation for large bundles.

packages/core/src/external/fhir/export/string/shared/telecom.ts (1)

1-51: LGTM - Well-structured formatting utilities.

The implementation follows TypeScript best practices and coding guidelines:

  • Uses proper destructuring parameters
  • Handles undefined cases gracefully
  • Follows immutable programming patterns
  • Uses meaningful function and parameter names
  • Implements consistent error handling by returning undefined

The debug functionality is well-implemented and the separation of concerns between formatting multiple telecoms vs. single telecom is appropriate.

packages/api/src/routes/ehr/eclinicalworks/auth/middleware.ts (2)

14-31: Security implementation looks solid.

The parseEClinicalWorksPracticeIdDash function properly validates:

  • Token source matches expected eClinicalWorks dash source
  • Required fields (practiceId and patientId) are present
  • Returns appropriate data structure with external ID and query parameters

The use of ForbiddenError for all validation failures is appropriate for security - it prevents information leakage about what specifically failed validation.


33-45: Middleware functions follow Express.js patterns correctly.

The middleware functions properly:

  • Use the correct Express.js signature (req, res, next)
  • Handle async operations with .then(next).catch(next)
  • Delegate to shared processing functions for consistency
  • Pass appropriate parameters including the source identifier

This follows the coding guidelines for error handling with async operations.

packages/core/src/external/opensearch/index.ts (2)

3-11: Well-structured configuration types.

The type definitions follow TypeScript best practices:

  • OpenSearchConfig provides a clean base interface
  • OpenSearchConfigDirectAccess extends appropriately with intersection types
  • Field names are clear and meaningful
  • Types are appropriately exported

The separation between basic config and direct access config is a good design pattern.


13-25: Generic response types improve type safety.

The addition of generic OpenSearchResponseHit<T> and OpenSearchResponse<T> types addresses the known issue in the OpenSearch JS client and provides better type safety. The GitHub issue reference is helpful for context.

The generic approach allows for type-safe handling of different response types throughout the codebase.

packages/core/src/command/consolidated/search/document-reference/search.ts (3)

3-12: Import path updates align with architectural refactoring.

The updated import paths reflect the new "external" directory structure and are consistent with the broader codebase reorganization mentioned in the AI summary. The deeper absolute paths improve modularity and organization.


14-26: Excellent JSDoc documentation.

The comprehensive JSDoc comment clearly explains:

  • Function purpose and behavior
  • Parameter descriptions
  • Return value specification
  • Important details about content filtering scope

This improves code maintainability and follows documentation best practices.


102-112: Local helper functions correctly implement document status logic.

The helper functions properly encapsulate document status checks:

  • isDocStatusReady: Correctly excludes preliminary and entered-in-error statuses
  • isDocStatusPreliminary: Simple, focused check
  • isDocStatusEnteredInError: Simple, focused check

This approach improves modularity by keeping the logic local to where it's used, replacing the previously imported functions.

packages/core/src/external/opensearch/shared/bulk.ts (2)

1-3: LGTM! Clean imports and type definitions.

The imports are well-organized and the type definitions follow TypeScript best practices.


70-93: LGTM! Well-structured function with good type safety.

The resourceToBulkRequest function is well-implemented with:

  • Clear parameter destructuring
  • Proper type annotations
  • Good separation of concerns
  • Functional approach without side effects
packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-direct.ts (1)

1-21: LGTM! Good imports and dayjs setup.

The imports are well-organized and the dayjs extension is properly configured.

packages/core/src/external/fhir/export/string/resources/diagnostic-report.ts (5)

16-17: LGTM! Good parameter addition and initialization.

The addition of the optional isDebug parameter and the initialization of hasMinimumData with defaultHasMinimumData follows good practices.


120-127: LGTM! Good implementation with proper data validation.

The presentedFormsToText integration is well-implemented with:

  • Proper iteration through forms
  • Debug-aware labeling
  • Minimum data tracking
  • Use of the singleLine helper function

153-153: LGTM! Proper minimum data validation.

The return of undefined when there's insufficient meaningful data follows the established pattern and prevents empty or meaningless output.


159-161: LGTM! Simple and effective helper function.

The singleLine helper function is well-implemented:

  • Single responsibility
  • Immutable (doesn't modify input)
  • Simple and readable

20-21: ⚠️ Potential issue

Fix parameter structure for formatIdentifiers.

The formatIdentifiers function expects an object with an identifiers property, but you're passing the identifiers directly.

-    const identifierStr = formatIdentifiers({ identifiers: report.identifier });
+    const identifierStr = formatIdentifiers({ identifiers: report.identifier });

Wait, looking at the relevant code snippet, the function signature is correct. The current implementation matches the expected signature from the relevant snippet. Let me reconsider...

Actually, the code is correct as written. The function expects { identifiers: Identifier[] | undefined } and that's exactly what's being passed.

Likely an incorrect or invalid review comment.

packages/core/src/external/fhir/export/string/shared/identifier.ts (3)

5-19: LGTM! Well-structured identifier formatting function.

The implementation correctly handles edge cases, uses appropriate functional programming patterns with flatMap, and provides proper deduplication. The type safety and early return patterns follow the coding guidelines well.


30-44: LGTM! Robust single identifier formatting.

The function properly handles validation, trimming, and system filtering. The use of some() with includes() for partial system matching is appropriate and follows functional programming principles.


52-58: LGTM! Useful convenience function for NPI filtering.

This helper function provides a clean interface for the common use case of filtering NPI identifiers, following the DRY principle by reusing the core formatIdentifiers function.

packages/core/src/external/fhir/export/string/shared/address.ts (2)

11-27: LGTM! Well-refactored function with improved API design.

The refactoring to use object parameters enhances readability and maintainability. The debug support and consistent return patterns align well with the broader FHIR formatting utilities.


29-50: LGTM! Clean address formatting implementation.

The function properly handles address component extraction and filtering. The decision to exclude country (line 44) and the separate handling of the text field (line 48) are reasonable design choices.

packages/core/src/external/fhir/export/string/resources/allergy-intolerance.ts (2)

13-119: LGTM! Consistent debug support implementation.

The toString method is properly updated to support debug mode with consistent parameter passing to all formatting helpers. The hasMinimumData tracking ensures meaningful output validation.


121-139: LGTM! Well-structured helper function for reaction formatting.

The function properly modularizes reaction formatting logic and maintains consistency with the debug parameter pattern used throughout the codebase.

packages/api/src/routes/internal/medical/patient-consolidated.ts (2)

153-175: LGTM! Clean ingestion route implementation.

The route properly validates parameters and handles the ingestion process. The fallback to all patients when no IDs are provided (lines 162-166) is a useful feature.

Note that the sequential processing approach aligns with the comment about this being designed for small patient volumes, with larger volumes requiring a queue-based architecture.


1-32: LGTM! Well-organized imports and setup.

The imports are properly structured and follow the coding guidelines. The dayjs plugin extension (line 30) follows the recommended pattern for date handling.

packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)

18-28: LGTM: Good use of options object pattern.

The refactoring from positional parameters to an options object improves maintainability and follows TypeScript best practices. The destructuring with defaults is well implemented.

packages/core/src/external/fhir/export/string/shared/coding.ts (1)

6-6:

✅ Verification successful

Clarify the internal code system pattern.

The INTERNAL_CODE_SYSTEM constant ends with a dot, which might be incomplete. Please verify this is the correct pattern for identifying internal codes.


🏁 Script executed:

#!/bin/bash
# Description: Search for other usages of internal code system patterns to verify correctness
# Expected: Find other references to internal OID patterns or similar filtering logic

rg -A 3 -B 3 "urn:oid:1\.2\.840" --type ts

Length of output: 4717


INTERNAL_CODE_SYSTEM prefix is correct.

The search confirms that FHIR codings use full OIDs like "urn:oid:1.2.840.114350…" in tests, so the trailing dot on "urn:oid:1.2.840." is intentional to match that prefix. No changes required.

packages/api/src/external/ehr/eclinicalworks/command/sync-patient.ts (1)

67-71: LGTM: Good async error handling pattern.

The use of .catch(processAsyncError(...)) for fire-and-forget async operations follows the coding guidelines correctly.

packages/core/src/external/ehr/eclinicalworks/index.ts (2)

35-39: LGTM: Good factory pattern implementation.

The static factory method with async initialization follows best practices for async object creation.


70-99: LGTM: Good delegation pattern.

The private makeRequest method properly delegates to the shared utility while providing the necessary context and configuration.

@@ -60,7 +60,7 @@ export async function handler(event: SQSEvent) {
}
const openSearch = new OpenSearchFileIngestorDirect({
region,
endpoint: "https://" + host,
endpoint: host,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify endpoint URL handling in the refactored modules.

The change from concatenating "https://" + host to passing host directly suggests the endpoint URL handling has been moved into the OpenSearchFileIngestorDirect constructor or related modules. Please ensure this change is consistent with how other OpenSearch modules handle endpoints.


🏁 Script executed:

#!/bin/bash
# Description: Verify endpoint handling in OpenSearch file ingestor modules
# Expected: Find how endpoint URLs are constructed in the new file structure

# Search for endpoint handling in OpenSearch file modules
ast-grep --pattern 'endpoint: $_'

# Check how OpenSearchFileIngestorDirect handles endpoint parameter
ast-grep --pattern 'class OpenSearchFileIngestorDirect {
  $$$
  constructor($_) {
    $$$
  }
  $$$
}'

# Look for "https://" prefix handling
rg -A 3 -B 3 "https://"

Length of output: 85649


🏁 Script executed:

#!/bin/bash
set -e

echo "=== 1. Imports and usage in sqs-to-opensearch-xml.ts ==="
grep -n "import.*Ingestor" -n packages/lambdas/src/sqs-to-opensearch-xml.ts || true
grep -n "new .*Ingestor" packages/lambdas/src/sqs-to-opensearch-xml.ts || true

echo
echo "=== 2. Locate Ingestor class definitions ==="
rg -n "class .*Ingestor" -n .

echo
echo "=== 3. Show constructor bodies for found Ingestor classes ==="
for file in $(rg -l "class .*Ingestor" --max-count 5 .); do
  echo "---- File: $file ----"
  # Print the class definition and constructor
  sed -n '/class .*Ingestor/,/^\}/p' "$file" | sed -n '/constructor/,/^\}/p'
done

Length of output: 15700


🏁 Script executed:

#!/bin/bash
set -e

echo "=== sqs-to-opensearch-xml.ts (first 200 lines) ==="
sed -n '1,200p' packages/lambdas/src/sqs-to-opensearch-xml.ts

echo
echo "=== Environment variable references ==="
grep -Rn "process.env" -n packages/lambdas/src/sqs-to-opensearch-xml.ts || true

Length of output: 5445


Ensure full URL is passed to OpenSearchFileIngestorDirect
The OpenSearchFileIngestorDirect constructor does not add a protocol prefix, it uses whatever you pass as endpoint directly in the Elasticsearch client. Previously you were doing "https://" + host in the Lambda, but now passing host alone means the client may receive an invalid URL if SEARCH_HOST doesn’t include http(s)://.

• packages/lambdas/src/sqs-to-opensearch-xml.ts (around line 61):

  • Confirm your SEARCH_HOST env var includes the protocol, e.g. https://my-domain.es.amazonaws.com
  • Or add a fallback in code, for example:
    const openSearch = new OpenSearchFileIngestorDirect({
      region,
      endpoint: host.startsWith("http") ? host : `https://${host}`,
      indexName,
      username,
      password,
    });

This will restore the previous behavior and prevent client errors if someone sets SEARCH_HOST without the protocol.

🤖 Prompt for AI Agents
In packages/lambdas/src/sqs-to-opensearch-xml.ts at line 63, the endpoint is
passed as host without the "https://" prefix, but OpenSearchFileIngestorDirect
expects a full URL including the protocol. Fix this by checking if host starts
with "http" and if not, prepend "https://" before passing it as the endpoint.
This ensures the client receives a valid URL regardless of how SEARCH_HOST is
set in the environment.

Comment on lines +48 to +65
router.post(
"/:id",
handleParams,
requestLogger,
asyncHandler(async (req: Request, res: Response) => {
const cxId = getCxIdOrFail(req);
const eclinicalworksPatientId = getFrom("params").orFail("id", req);
const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req);
const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req);
const patientId = await syncEClinicalWorksPatientIntoMetriport({
cxId,
eclinicalworksPracticeId,
eclinicalworksPatientId,
eclinicalworksTokenId,
});
return res.status(httpStatus.OK).json(patientId);
})
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Remove duplicate POST route implementation.

This POST route is identical to the GET route above, creating unnecessary code duplication. If both HTTP methods are intentionally supported, they should share the same handler function.

After implementing the shared handler from the previous comment:

 router.post(
   "/:id",
   handleParams,
   requestLogger,
-  asyncHandler(async (req: Request, res: Response) => {
-    const cxId = getCxIdOrFail(req);
-    const eclinicalworksPatientId = getFrom("params").orFail("id", req);
-    const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req);
-    const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req);
-    const patientId = await syncEClinicalWorksPatientIntoMetriport({
-      cxId,
-      eclinicalworksPracticeId,
-      eclinicalworksPatientId,
-      eclinicalworksTokenId,
-    });
-    return res.status(httpStatus.OK).json(patientId);
-  })
+  handlePatientSync
 );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
router.post(
"/:id",
handleParams,
requestLogger,
asyncHandler(async (req: Request, res: Response) => {
const cxId = getCxIdOrFail(req);
const eclinicalworksPatientId = getFrom("params").orFail("id", req);
const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req);
const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req);
const patientId = await syncEClinicalWorksPatientIntoMetriport({
cxId,
eclinicalworksPracticeId,
eclinicalworksPatientId,
eclinicalworksTokenId,
});
return res.status(httpStatus.OK).json(patientId);
})
);
router.post(
"/:id",
handleParams,
requestLogger,
handlePatientSync
);
🤖 Prompt for AI Agents
In packages/api/src/routes/ehr/eclinicalworks/patient.ts around lines 48 to 65,
there is a duplicate POST route implementation identical to the GET route above.
To fix this, extract the async handler function into a separate named function
and reuse it for both the POST and GET routes. This will remove code duplication
and ensure both routes share the same logic.

Comment on lines +20 to +37
router.get(
"/:id",
handleParams,
requestLogger,
asyncHandler(async (req: Request, res: Response) => {
const cxId = getCxIdOrFail(req);
const eclinicalworksPatientId = getFrom("params").orFail("id", req);
const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req);
const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req);
const patientId = await syncEClinicalWorksPatientIntoMetriport({
cxId,
eclinicalworksPracticeId,
eclinicalworksPatientId,
eclinicalworksTokenId,
});
return res.status(httpStatus.OK).json(patientId);
})
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider consolidating duplicate route logic.

The GET route implementation looks correct, but there's significant code duplication between the GET and POST routes (lines 20-37 and 48-65). This violates the DRY principle mentioned in the coding guidelines.

Consider extracting the common logic into a shared function:

+const handlePatientSync = asyncHandler(async (req: Request, res: Response) => {
+  const cxId = getCxIdOrFail(req);
+  const eclinicalworksPatientId = getFrom("params").orFail("id", req);
+  const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req);
+  const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req);
+  const patientId = await syncEClinicalWorksPatientIntoMetriport({
+    cxId,
+    eclinicalworksPracticeId,
+    eclinicalworksPatientId,
+    eclinicalworksTokenId,
+  });
+  return res.status(httpStatus.OK).json({ patientId });
+});

 router.get(
   "/:id",
   handleParams,
   requestLogger,
-  asyncHandler(async (req: Request, res: Response) => {
-    const cxId = getCxIdOrFail(req);
-    const eclinicalworksPatientId = getFrom("params").orFail("id", req);
-    const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req);
-    const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req);
-    const patientId = await syncEClinicalWorksPatientIntoMetriport({
-      cxId,
-      eclinicalworksPracticeId,
-      eclinicalworksPatientId,
-      eclinicalworksTokenId,
-    });
-    return res.status(httpStatus.OK).json(patientId);
-  })
+  handlePatientSync
 );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
router.get(
"/:id",
handleParams,
requestLogger,
asyncHandler(async (req: Request, res: Response) => {
const cxId = getCxIdOrFail(req);
const eclinicalworksPatientId = getFrom("params").orFail("id", req);
const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req);
const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req);
const patientId = await syncEClinicalWorksPatientIntoMetriport({
cxId,
eclinicalworksPracticeId,
eclinicalworksPatientId,
eclinicalworksTokenId,
});
return res.status(httpStatus.OK).json(patientId);
})
);
// Extract and reuse the shared handler for both GET and POST routes
const handlePatientSync = asyncHandler(async (req: Request, res: Response) => {
const cxId = getCxIdOrFail(req);
const eclinicalworksPatientId = getFrom("params").orFail("id", req);
const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req);
const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req);
const patientId = await syncEClinicalWorksPatientIntoMetriport({
cxId,
eclinicalworksPracticeId,
eclinicalworksPatientId,
eclinicalworksTokenId,
});
// Return a structured response
return res.status(httpStatus.OK).json({ patientId });
});
// GET route
router.get(
"/:id",
handleParams,
requestLogger,
handlePatientSync
);
🤖 Prompt for AI Agents
In packages/api/src/routes/ehr/eclinicalworks/patient.ts around lines 20 to 37,
the GET and POST routes contain duplicated logic for extracting parameters and
calling syncEClinicalWorksPatientIntoMetriport. To fix this, extract the shared
logic into a separate async function that accepts the request object, performs
the parameter extraction and patient sync, and returns the patientId. Then,
update both the GET and POST route handlers to call this new function and return
its result, eliminating duplication and adhering to the DRY principle.

Comment on lines +56 to +60
export function processAsyncError(
msg: string,
log?: typeof console.log | undefined,
useMsgAsTitle = false
) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve parameter handling to avoid non-null assertion.

The log parameter is typed as optional but then requires a non-null assertion operator on line 64. Consider making it required or handle the undefined case properly.

Apply this diff to improve the parameter handling:

-export function processAsyncError(
-  msg: string,
-  log?: typeof console.log | undefined,
-  useMsgAsTitle = false
-) {
-  if (!log) log = out().log;
+export function processAsyncError(
+  msg: string,
+  log: typeof console.log = out().log,
+  useMsgAsTitle = false
+) {
🤖 Prompt for AI Agents
In packages/core/src/util/error/shared.ts around lines 56 to 60, the optional
parameter 'log' is used with a non-null assertion later, which is unsafe. To fix
this, either make the 'log' parameter required by removing the optional modifier
or add a check to handle the case when 'log' is undefined before using it,
ensuring no non-null assertion is needed.

Comment on lines +176 to +185
it("should handle undefined values in repeat rules", () => {
const timing: Timing = {
repeat: {
frequency: undefined as unknown as number,
period: undefined as unknown as number,
periodUnit: undefined as unknown as "s" | "min" | "h" | "d" | "wk" | "mo" | "a",
},
};
expect(formatTiming({ timing })).toBeUndefined();
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve type safety in test.

The use of as unknown as type assertions to force undefined values should be avoided as it bypasses TypeScript's type safety.

Consider testing with a more realistic scenario or using a different approach:

-  const timing: Timing = {
-    repeat: {
-      frequency: undefined as unknown as number,
-      period: undefined as unknown as number,
-      periodUnit: undefined as unknown as "s" | "min" | "h" | "d" | "wk" | "mo" | "a",
-    },
-  };
+  const timing: Timing = {
+    repeat: {},
+  };
🤖 Prompt for AI Agents
In packages/core/src/external/fhir/export/string/shared/__tests__/timing.test.ts
around lines 176 to 185, the test uses unsafe type assertions with 'as unknown
as' to assign undefined to typed properties, which bypasses TypeScript's type
safety. To fix this, remove the forced type assertions and instead test with
either optional properties omitted or assign values that are valid but represent
absence or edge cases according to the Timing type definition, ensuring the test
remains type-safe and realistic.

Comment on lines +42 to +65
export function formatCoding({
coding,
skipInternalCodes,
}: {
coding: Coding | undefined;
skipInternalCodes?: boolean | undefined;
}): string | undefined {
if (!coding) return undefined;
if (skipInternalCodes && isInternalCoding(coding)) return undefined;

const system = isAllowedSystem(coding.system);
if (!system) return undefined;
const code = getCode({ coding, skipInternalCodes });
const displayPre = emptyIfDenied(coding.display);
const display = displayPre ? displayPre.trim() : undefined;

if (code) return codeAndDisplayToString(code, display);

const altCode = "";
const codeAndDisplay = codeAndDisplayToString(altCode, coding.display);
if (!codeAndDisplay) return undefined;

return codeAndDisplay;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify function logic and improve readability.

The function has redundant logic and could be simplified for better maintainability.

 export function formatCoding({
   coding,
   skipInternalCodes,
 }: {
   coding: Coding | undefined;
   skipInternalCodes?: boolean | undefined;
 }): string | undefined {
   if (!coding) return undefined;
   if (skipInternalCodes && isInternalCoding(coding)) return undefined;
 
   const system = isAllowedSystem(coding.system);
   if (!system) return undefined;
   
   const code = getCode({ coding, skipInternalCodes });
   const displayPre = emptyIfDenied(coding.display);
   const display = displayPre ? displayPre.tri
F438
m() : undefined;
 
-  if (code) return codeAndDisplayToString(code, display);
-
-  const altCode = "";
-  const codeAndDisplay = codeAndDisplayToString(altCode, coding.display);
-  if (!codeAndDisplay) return undefined;
-
-  return codeAndDisplay;
+  return codeAndDisplayToString(code, display);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function formatCoding({
coding,
skipInternalCodes,
}: {
coding: Coding | undefined;
skipInternalCodes?: boolean | undefined;
}): string | undefined {
if (!coding) return undefined;
if (skipInternalCodes && isInternalCoding(coding)) return undefined;
const system = isAllowedSystem(coding.system);
if (!system) return undefined;
const code = getCode({ coding, skipInternalCodes });
const displayPre = emptyIfDenied(coding.display);
const display = displayPre ? displayPre.trim() : undefined;
if (code) return codeAndDisplayToString(code, display);
const altCode = "";
const codeAndDisplay = codeAndDisplayToString(altCode, coding.display);
if (!codeAndDisplay) return undefined;
return codeAndDisplay;
}
export function formatCoding({
coding,
skipInternalCodes,
}: {
coding: Coding | undefined;
skipInternalCodes?: boolean | undefined;
}): string | undefined {
if (!coding) return undefined;
if (skipInternalCodes && isInternalCoding(coding)) return undefined;
const system = isAllowedSystem(coding.system);
if (!system) return undefined;
const code = getCode({ coding, skipInternalCodes });
const displayPre = emptyIfDenied(coding.display);
const display = displayPre ? displayPre.trim() : undefined;
return codeAndDisplayToString(code, display);
}
🤖 Prompt for AI Agents
In packages/core/src/external/fhir/export/string/shared/coding.ts between lines
42 and 65, the formatCoding function contains redundant checks and variable
assignments that can be streamlined. Simplify by removing unnecessary variables
like altCode and directly returning results where possible, consolidating
conditional returns, and trimming the display value once to improve readability
and maintainability without changing the function's behavior.

Comment on lines +25 to +79
export async function syncEClinicalWorksPatientIntoMetriport({
cxId,
eclinicalworksPracticeId,
eclinicalworksPatientId,
eclinicalworksTokenId,
api,
triggerDq = false,
}: SyncEClinicalWorksPatientIntoMetriportParams): Promise<string> {
const existingPatient = await getPatientMapping({
cxId,
externalId: eclinicalworksPatientId,
source: EhrSources.eclinicalworks,
});
if (existingPatient) {
const metriportPatient = await getPatientOrFail({
cxId,
id: existingPatient.patientId,
});
const metriportPatientId = metriportPatient.id;
return metriportPatientId;
}

const eclinicalworksApi =
api ??
(await createEClinicalWorksClientFromTokenId({
cxId,
practiceId: eclinicalworksPracticeId,
tokenId: eclinicalworksTokenId,
}));
const eclinicalworksPatient = await eclinicalworksApi.getPatient({
cxId,
patientId: eclinicalworksPatientId,
});
const possibleDemographics = createMetriportPatientDemosFhir(eclinicalworksPatient);
const metriportPatient = await getOrCreateMetriportPatientFhir({
cxId,
source: EhrSources.eclinicalworks,
practiceId: eclinicalworksPracticeId,
possibleDemographics,
externalId: eclinicalworksPatientId,
});
if (triggerDq) {
queryDocumentsAcrossHIEs({
cxId,
patientId: metriportPatient.id,
}).catch(processAsyncError(`EClinicalWorks queryDocumentsAcrossHIEs`));
}
await findOrCreatePatientMapping({
cxId,
patientId: metriportPatient.id,
externalId: eclinicalworksPatientId,
source: EhrSources.eclinicalworks,
});
return metriportPatient.id;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider decomposing the main function for better maintainability.

The syncEClinicalWorksPatientIntoMetriport function handles multiple responsibilities. Consider breaking it down into smaller, focused functions.

+async function handleExistingPatient(
+  cxId: string,
+  externalId: string
+): Promise<string | null> {
+  const existingPatient = await getPatientMapping({
+    cxId,
+    externalId,
+    source: EhrSources.eclinicalworks,
+  });
+  if (existingPatient) {
+    const metriportPatient = await getPatientOrFail({
+      cxId,
+      id: existingPatient.patientId,
+    });
+    return metriportPatient.id;
+  }
+  return null;
+}
+
+async function createAndSyncNewPatient(
+  params: SyncEClinicalWorksPatientIntoMetriportParams
+): Promise<string> {
+  const {
+    cxId,
+    eclinicalworksPracticeId,
+    eclinicalworksPatientId,
+    eclinicalworksTokenId,
+    api,
+    triggerDq = false,
+  } = params;
+
+  const eclinicalworksApi =
+    api ??
+    (await createEClinicalWorksClientFromTokenId({
+      cxId,
+      practiceId: eclinicalworksPracticeId,
+      tokenId: eclinicalworksTokenId,
+    }));
+    
+  // ... rest of the logic
+}
+
 export async function syncEClinicalWorksPatientIntoMetriport({
   cxId,
   eclinicalworksPracticeId,
   eclinicalworksPatientId,
   eclinicalworksTokenId,
   api,
   triggerDq = false,
 }: SyncEClinicalWorksPatientIntoMetriportParams): Promise<string> {
-  const existingPatient = await getPatientMapping({
-    cxId,
-    externalId: eclinicalworksPatientId,
-    source: EhrSources.eclinicalworks,
-  });
-  if (existingPatient) {
-    const metriportPatient = await getPatientOrFail({
-      cxId,
-      id: existingPatient.patientId,
-    });

10000
-    const metriportPatientId = metriportPatient.id;
-    return metriportPatientId;
-  }
+  const existingPatientId = await handleExistingPatient(cxId, eclinicalworksPatientId);
+  if (existingPatientId) {
+    return existingPatientId;
+  }
+
+  return await createAndSyncNewPatient({
+    cxId,
+    eclinicalworksPracticeId,
+    eclinicalworksPatientId,
+    eclinicalworksTokenId,
+    api,
+    triggerDq,
+  });
 }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/api/src/external/ehr/eclinicalworks/command/sync-patient.ts between
lines 25 and 79, the syncEClinicalWorksPatientIntoMetriport function is doing
too many tasks such as checking existing patients, creating API clients,
fetching patient data, and triggering data queries. Refactor by extracting these
distinct responsibilities into smaller helper functions like
checkExistingPatientMapping, fetchEClinicalWorksPatientData,
createOrUpdateMetriportPatient, and triggerDataQualityChecks. Then call these
helpers from the main function to improve readability and maintainability.

Comment on lines +51 to +68
async getPatient({ cxId, patientId }: { cxId: string; patientId: string }): Promise<Patient> {
const { debug } = out(
`EClinicalWorks getPatient - cxId ${cxId} practiceId ${this.practiceId} patientId ${patientId}`
);
const patientUrl = `/Patient/${patientId}`;
const additionalInfo = { cxId, practiceId: this.practiceId, patientId };
const patient = await this.makeRequest<Patient>({
cxId,
patientId,
s3Path: "patient",
method: "GET",
url: patientUrl,
schema: patientSchema,
additionalInfo,
debug,
});
return patient;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding error handling for API calls.

The getPatient method doesn't handle potential errors from the API call. Consider adding try-catch for better error handling and logging.

   async getPatient({ cxId, patientId }: { cxId: string; patientId: string }): Promise<Patient> {
     const { debug } = out(
       `EClinicalWorks getPatient - cxId ${cxId} practiceId ${this.practiceId} patientId ${patientId}`
     );
     const patientUrl = `/Patient/${patientId}`;
     const additionalInfo = { cxId, practiceId: this.practiceId, patientId };
-    const patient = await this.makeRequest<Patient>({
-      cxId,
-      patientId,
-      s3Path: "patient",
-      method: "GET",
-      url: patientUrl,
-      schema: patientSchema,
-      additionalInfo,
-      debug,
-    });
-    return patient;
+    try {
+      const patient = await this.makeRequest<Patient>({
+        cxId,
+        patientId,
+        s3Path: "patient",
+        method: "GET",
+        url: patientUrl,
+        schema: patientSchema,
+        additionalInfo,
+        debug,
+      });
+      return patient;
+    } catch (error) {
+      debug(`Failed to get patient: ${error}`);
+      throw error;
+    }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async getPatient({ cxId, patientId }: { cxId: string; patientId: string }): Promise<Patient> {
const { debug } = out(
`EClinicalWorks getPatient - cxId ${cxId} practiceId ${this.practiceId} patientId ${patientId}`
);
const patientUrl = `/Patient/${patientId}`;
const additionalInfo = { cxId, practiceId: this.practiceId, patientId };
const patient = await this.makeRequest<Patient>({
cxId,
patientId,
s3Path: "patient",
method: "GET",
url: patientUrl,
schema: patientSchema,
additionalInfo,
debug,
});
return patient;
}
async getPatient({ cxId, patientId }: { cxId: string; patientId: string }): Promise<Patient> {
const { debug } = out(
`EClinicalWorks getPatient - cxId ${cxId} practiceId ${this.practiceId} patientId ${patientId}`
);
const patientUrl = `/Patient/${patientId}`;
const additionalInfo = { cxId, practiceId: this.practiceId, patientId };
try {
const patient = await this.makeRequest<Patient>({
cxId,
patientId,
s3Path: "patient",
method: "GET",
url: patientUrl,
schema: patientSchema,
additionalInfo,
debug,
});
return patient;
} catch (error) {
debug(`Failed to get patient: ${error}`);
throw error;
}
}
🤖 Prompt for AI Agents
In packages/core/src/external/ehr/eclinicalworks/index.ts around lines 51 to 68,
the getPatient method lacks error handling for the API call. Wrap the await
this.makeRequest call inside a try-catch block, catch any errors thrown during
the request, log the error with relevant context including cxId and patientId,
and rethrow or handle the error appropriately to ensure failures are managed
gracefully.

Comment on lines +44 to +48
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/x-www-form-urlencoded",
},
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Reconsider hard-coded Content-Type header.

The Content-Type is set to "application/x-www-form-urlencoded" but this might not be appropriate for all API calls, especially FHIR endpoints which typically use "application/fhir+json".


🌐 Web query:

What Content-Type headers does EClinicalWorks FHIR API expect for different operations?

💡 Result:

Content-Type Headers Expected by eClinicalWorks FHIR API

eClinicalWorks FHIR API adheres to the general FHIR standard for HTTP headers and MIME types. Although official eClinicalWorks documentation on this particular header is limited in the provided search results, typical FHIR API expectations, referenced by multiple sources, apply to their endpoints.

Standard FHIR Content-Type Headers

Depending on the type of operation (fetching data, sending new resources, updating records), the following Content-Type headers are used:

  • Reading Data (GET requests):

    • Header: Accept: application/fhir+json (or application/fhir+xml if XML is required)
    • This specifies the expected format for the response. JSON is the most common format in contemporary implementations[2][5].
  • Creating or Updating Data (POST/PUT requests):

    • Header: Content-Type: application/fhir+json
    • This indicates the format being sent in the request body. JSON is the preferred format, following the modern FHIR API conventions[2][5][9].
  • Partial Updates (PATCH requests):

    • Header: Content-Type: application/json-patch+json or application/fhir+json
    • Though PATCH is less frequently used, partial resource modifications may require application/json-patch+json as per the FHIR specification[3].

Table: Common FHIR Operations and Headers

Operation HTTP Method Content-Type (Request) Accept (Response)
Read (e.g., retrieve patient) GET application/fhir+json
Create (e.g., add patient) POST application/fhir+json application/fhir+json
Update (replace resource) PUT application/fhir+json application/fhir+json
Patch (partial update) PATCH application/json-patch+json application/fhir+json
Delete DELETE
  • For read and delete operations, a Content-Type header is typically not necessary, though the Accep 10000 t header determines the response format[2][5][9].

eClinicalWorks-Specific Integration Guidance

  • eClinicalWorks uses RESTful FHIR APIs, and integrations are expected to comply with standard FHIR headers when making requests to their endpoints[6][10].
  • The default and preferred format is JSON, i.e., application/fhir+json[2][9].
  • Authorization is handled separately and generally requires an Authorization header with a Bearer token.

Default Encoding and Fallback Behavior

If the Accept or Content-Type headers are not specified:

  • Most FHIR servers, including implementations like eClinicalWorks, default to returning and processing application/fhir+json[5].
  • If both Accept and _format are provided, _format takes precedence[5].

Summary

For all practical operations with the eClinicalWorks FHIR API:

  • Use Content-Type: application/fhir+json for all POST and PUT requests.
  • Use Accept: application/fhir+json to specify response format, especially in GET requests.
  • For PATCH, use Content-Type: application/json-patch+json as needed.
  • Always include an Authorization header per API requirements[2][5][9].

These expectations follow the standard FHIR conventions and are supported by eClinicalWorks in their integration offerings.

Citations:


🏁 Script executed:

#!/bin/bash
# Search for Content-Type occurrences in the file
rg '"Content-Type"' -n packages/core/src/external/ehr/eclinicalworks/index.ts || true

# Display the file contents around the OAuth/token request to understand context
sed -n '1,200p' packages/core/src/external/ehr/eclinicalworks/index.ts

Length of output: 3160


Update default FHIR Content-Type header

The hard-coded "application/x-www-form-urlencoded" in your FHIR client initialization will break JSON-based FHIR operations. Instead, remove or override the default and set headers per operation:

• File: packages/core/src/external/ehr/eclinicalworks/index.ts
– In initialize(), replace the default headers block:

- this.axiosFhirInstance = axios.create({
-   baseURL: `${this.baseFhirUrl}/fhir/r4/${this.practiceId}`,
-   headers: {
-     Authorization: `Bearer ${this.token}`,
-     "Content-Type": "application/x-www-form-urlencoded",
-   },
- });
+ this.axiosFhirInstance = axios.create({
+   baseURL: `${this.baseFhirUrl}/fhir/r4/${this.practiceId}`,
+   headers: {
+     Authorization: `Bearer ${this.token}`,
+     // Default Accept for all GET/DELETE
+     Accept: "application/fhir+json",
+   },
+});

• In each request that sends or patches data, override Content-Type appropriately:

  • POST/PUT → "application/fhir+json"
  • PATCH → "application/json-patch+json"

For example, inside makeRequest:

await makeRequest<T>({,
  headers: {
    "Content-Type": "application/fhir+json",
    …headers,
  },});

This ensures GET/DELETE use Accept: application/fhir+json and write operations send the correct FHIR JSON payload.

🤖 Prompt for AI Agents
In packages/core/src/external/ehr/eclinicalworks/index.ts around lines 44 to 48,
the Content-Type header is hard-coded to "application/x-www-form-urlencoded",
which is incorrect for FHIR JSON operations. Remove this default header from
initialization and instead set Content-Type dynamically per request: use
"application/fhir+json" for POST and PUT requests, "application/json-patch+json"
for PATCH requests, and omit Content-Type for GET and DELETE while setting
Accept to "application/fhir+json". Update the makeRequest calls to include these
headers accordingly to comply with FHIR API standards.

Comment on lines +101 to +108
const response = await client.index(
{
index: indexName,
id: entryId,
body: { doc: document, doc_as_upsert: true },
},
{ requestTimeout: DEFAULT_INGESTION_TIMEOUT }
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Incorrect API used – upsert will silently fail

client.index() does not understand the doc / doc_as_upsert syntax; that belongs to the update API.
The current call will create a document containing the fields doc and doc_as_upsert instead of performing an upsert, breaking idempotency and update semantics.

-    const response = await client.index(
+    const response = await client.update(
       {
         index: indexName,
         id: entryId,
         body: { doc: document, doc_as_upsert: true },
       },
       { requestTimeout: DEFAULT_INGESTION_TIMEOUT }
     );

Please switch to client.update() (or remove the wrapper and use client.index() with the full source) and add a regression test – otherwise later updates will be silently ignored.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const response = await client.index(
{
index: indexName,
id: entryId,
body: { doc: document, doc_as_upsert: true },
},
{ requestTimeout: DEFAULT_INGESTION_TIMEOUT }
);
const response = await client.update(
{
index: indexName,
id: entryId,
body: { doc: document, doc_as_upsert: true },
},
{ requestTimeout: DEFAULT_INGESTION_TIMEOUT }
);
🤖 Prompt for AI Agents
In packages/core/src/external/opensearch/text-ingestor.ts around lines 101 to
108, the code incorrectly uses client.index() with doc and doc_as_upsert fields,
which are only valid for client.update(). To fix this, replace client.index()
with client.update() and pass the document inside the doc field along with
doc_as_upsert: true to enable upsert behavior. Additionally, add a regression
test to verify that updates are correctly applied and not silently ignored.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0