Skip to content

Conversation

thomasyopes
Copy link
Contributor

@thomasyopes thomasyopes commented Jul 9, 2025

Issues:

Description

Testing

Check each PR.

Release Plan

  • ⚠️ Points to master
  • Merge this

Summary by CodeRabbit

  • New Features

    • Added support for the Healthie EHR system, enabling retrieval and bundling of MedicationStatement, Immunization, AllergyIntolerance, Condition, and Observation data in FHIR format.
    • Introduced validation and typing for Healthie-related medication, immunization, lab, allergy, and condition data.
    • Expanded system capabilities to fetch and process Healthie-specific resource bundles.
  • Infrastructure

    • Adjusted queue alarm thresholds, lambda timeouts, and concurrency limits for improved reliability.
    • Integrated optional S3 bucket support for relevant EHR lambda functions.

Thomas Yopes and others added 16 commits July 1, 2025 15:26
Ref: ENG-535

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
Ref: ENG-412

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
Ref: ENG-412

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
Ref: ENG-412

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
Ref: ENG-412

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
…-healthie-contribution

Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
Ref: ENG-412

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
Ref: ENG-412

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
Ref: ENG-412

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
Ref: ENG-412

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
Ref: ENG-412

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
Ref: ENG-412

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
…-healthie-contribution

Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
Ref: ENG-412

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
Ref: ENG-412

Ref: #1040
Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
Copy link

coderabbitai bot commented Jul 9, 2025

Walkthrough

The changes introduce comprehensive support for the Healthie EHR source across multiple packages. This includes adding new resource types (MedicationStatement, Immunization, AllergyIntolerance, Condition, Observation), implementing resource fetching and conversion logic, updating bundle and diff bundle handling, and extending validation schemas and type exports for Healthie-specific data structures.

Changes

File(s) / Area Change Summary
.../src/external/ehr/healthie/index.ts
.../medication.ts
.../immunization.ts
.../lab.ts
.../allergy.ts
.../condition.ts
Added new modules and exports for Healthie resource types: medication, immunization, lab, allergy, and condition. Each module defines Zod schemas and TypeScript types for strict validation and typing of corresponding Healthie data and GraphQL responses. The index file re-exports all resource modules for centralized access.
.../src/external/ehr/healthie/command/get-bundle-by-resource-type.ts Introduced a new async function to fetch and return a FHIR Bundle for a given resource type from Healthie, using a Healthie client and mapping parameters as needed.
.../src/external/ehr/healthie/index.ts Added methods to fetch, validate, and convert MedicationStatement, Immunization, AllergyIntolerance, Condition, and Observation resources from Healthie to FHIR, including resource-type-specific GraphQL queries and FHIR conversion logic. Added a method to return a FHIR Bundle for a requested resource type. Exported supported resource lists, type guards, and utility functions.
.../src/external/ehr/bundle/bundle-shared.ts Added support for Healthie in getSupportedResourcesByEhr, returning supported Healthie resources when the source matches.
.../src/external/ehr/command/get-bundle-by-resource-type.ts Registered Healthie’s getBundleByResourceType handler in the EHR resource type fetch map, enabling bundle retrieval for Healthie.
.../src/external/ehr/job/create-resource-diff-bundles/shared.ts Updated the list and type alias of EHR sources supporting resource diff bundles to include Healthie.
.../src/external/ehr/shared/command/bundle/contribute-resource-diff-bundle.ts Added a conditional check to exit early if the EHR source is Healthie, preventing further processing for this source.
.../src/interface/external/ehr/healthie/index.ts Re-exported all new Healthie resource modules for centralized access.
.../src/interface/external/ehr/healthie/medication.ts
.../immunization.ts
.../lab.ts
.../allergy.ts
.../condition.ts
Added Zod schemas and TypeScript types for Healthie medication, immunization, lab, allergy, and condition data and their respective GraphQL response wrappers.
.../lib/ehr-nested-stack.ts Adjusted SQS queue alarm thresholds, lambda timeouts, and concurrency for resource bundle jobs. Integrated optional ehrResponsesBucket into relevant lambdas, with environment variables and permissions.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API
    participant HealthieApi
    participant HealthieGraphQL

    Client->>API: Request resource bundle (Healthie, resourceType)
    API->>HealthieApi: getBundleByResourceType({cxId, patientId, resourceType})
    HealthieApi->>HealthieGraphQL: Query for resourceType data
    HealthieGraphQL-->>HealthieApi: Return resource data
    HealthieApi->>HealthieApi: Validate & convert to FHIR
    HealthieApi-->>API: Return FHIR Bundle
    API-->>Client: Respond with FHIR Bundle
Loading

Possibly related PRs

  • metriport/metriport#4143: Adds Healthie EHR source support, overlapping with this PR in resource fetching, FHIR conversion, bundle handling, and contribution logic.
  • metriport/metriport#3788: Refactors and enhances resource diff bundle handling for EHR integrations, including logic now extended for Healthie in this PR.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm error code ERR_SSL_WRONG_VERSION_NUMBER
npm error errno ERR_SSL_WRONG_VERSION_NUMBER
npm error request to https://10.0.0.28:4873/punycode/-/punycode-2.3.1.tgz failed, reason: C01C7D793B7F0000:error:0A00010B:SSL routines:ssl3_get_record:wrong version number:../deps/openssl/openssl/ssl/record/ssl3_record.c:354:
npm error
npm error A complete log of this run can be found in: /.npm/_logs/2025-07-09T16_36_47_613Z-debug-0.log

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

🧹 Nitpick comments (1)
packages/shared/src/interface/external/ehr/healthie/immunization.ts (1)

3-9: Solid validation; consider datetime() in follow-up

Everything is correct. A future refinement (non-blocking for this release) could switch received_at to z.string().datetime() once Healthie guarantees ISO-8601 formatting.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9663255 and 7f19f26.

📒 Files selected for processing (13)
  • packages/api/src/external/ehr/shared/command/bundle/contribute-resource-diff-bundle.ts (2 hunks)
  • packages/core/src/external/ehr/bundle/bundle-shared.ts (2 hunks)
  • packages/core/src/external/ehr/command/get-bundle-by-resource-type.ts (2 hunks)
  • packages/core/src/external/ehr/healthie/command/get-bundle-by-resource-type.ts (1 hunks)
  • packages/core/src/external/ehr/healthie/index.ts (5 hunks)
  • packages/core/src/external/ehr/job/create-resource-diff-bundles/shared.ts (1 hunks)
  • packages/infra/lib/ehr-nested-stack.ts (10 hunks)
  • packages/shared/src/interface/external/ehr/healthie/allergy.ts (1 hunks)
  • packages/shared/src/interface/external/ehr/healthie/condition.ts (1 hunks)
  • packages/shared/src/interface/external/ehr/healthie/immunization.ts (1 hunks)
  • packages/shared/src/interface/external/ehr/healthie/index.ts (1 hunks)
  • packages/shared/src/interface/external/ehr/healthie/lab.ts (1 hunks)
  • packages/shared/src/interface/external/ehr/healthie/medication.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
`**/*.{js,jsx,ts,tsx}`: Don’t use null inside the app, only on code interacting ...

**/*.{js,jsx,ts,tsx}: 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 const whenever possible
Use async/await instead of .then()
Naming: classes, enums: PascalCase
Naming: constants, variables, functions: camelCase
Naming: file names: kebab-case
Naming: Don’t use negative names, like notEnabled, prefer isDisabled
If possible, use decomposing objects for function parameters
Prefer Nullish Coalesce (??) than the OR operator (||) when you want to provide a default value
Avoid creating arrow functions
Use truthy syntax instead of in - i.e., if (data.link) not if ('link' in data)
While handling errors, keep the stack trace around: if you create a new Error (e.g., MetriportError), make sure to pass the original error as the new one’s cause so the stack trace is available upstream.
max column length is 100 chars
multi-line comments use /** */
top-level comments go after the import (save pre-import to basic file header, like license)
move literals to constants declared after imports when possible

📄 Source: CodeRabbit Inference Engine (.cursorrules)

List of files the instruction was applied to:

  • packages/core/src/external/ehr/command/get-bundle-by-resource-type.ts
  • packages/api/src/external/ehr/shared/command/bundle/contribute-resource-diff-bundle.ts
  • packages/core/src/external/ehr/job/create-resource-diff-bundles/shared.ts
  • packages/shared/src/interface/external/ehr/healthie/index.ts
  • packages/core/src/external/ehr/healthie/command/get-bundle-by-resource-type.ts
  • packages/shared/src/interface/external/ehr/healthie/medication.ts
  • packages/shared/src/interface/external/ehr/healthie/lab.ts
  • packages/core/src/external/ehr/bundle/bundle-shared.ts
  • packages/shared/src/interface/external/ehr/healthie/condition.ts
  • packages/shared/src/interface/external/ehr/healthie/immunization.ts
  • packages/infra/lib/ehr-nested-stack.ts
  • packages/shared/src/interface/external/ehr/healthie/allergy.ts
  • packages/core/src/external/ehr/healthie/index.ts
`**/*.{ts,tsx}`: Use types whenever possible

**/*.{ts,tsx}: Use types whenever possible

📄 Source: CodeRabbit Inference Engine (.cursorrules)

List of files the instruction was applied to:

  • packages/core/src/external/ehr/command/get-bundle-by-resource-type.ts
  • packages/api/src/external/ehr/shared/command/bundle/contribute-resource-diff-bundle.ts
  • packages/core/src/external/ehr/job/create-resource-diff-bundles/shared.ts
  • packages/shared/src/interface/external/ehr/healthie/index.ts
  • packages/core/src/external/ehr/healthie/command/get-bundle-by-resource-type.ts
  • packages/shared/src/interface/external/ehr/healthie/medication.ts
  • packages/shared/src/interface/external/ehr/healthie/lab.ts
  • packages/core/src/external/ehr/bundle/bundle-shared.ts
  • packages/shared/src/interface/external/ehr/healthie/condition.ts
  • packages/shared/src/interface/external/ehr/healthie/immunization.ts
  • packages/infra/lib/ehr-nested-stack.ts
  • packages/shared/src/interface/external/ehr/healthie/allergy.ts
  • packages/core/src/external/ehr/healthie/index.ts
`**/*.ts`: - Use the Onion Pattern to organize a package's code in layers - 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 default 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

⚙️ Source: CodeRabbit Configuration File

List of files the instruction was applied to:

  • packages/core/src/external/ehr/command/get-bundle-by-resource-type.ts
  • packages/api/src/external/ehr/shared/command/bundle/contribute-resource-diff-bundle.ts
  • packages/core/src/external/ehr/job/create-resource-diff-bundles/shared.ts
  • packages/shared/src/interface/external/ehr/healthie/index.ts
  • packages/core/src/external/ehr/healthie/command/get-bundle-by-resource-type.ts
  • packages/shared/src/interface/external/ehr/healthie/medication.ts
  • packages/shared/src/interface/external/ehr/healthie/lab.ts
  • packages/core/src/external/ehr/bundle/bundle-shared.ts
  • packages/shared/src/interface/external/ehr/healthie/condition.ts
  • packages/shared/src/interface/external/ehr/healthie/immunization.ts
  • packages/infra/lib/ehr-nested-stack.ts
  • packages/shared/src/interface/external/ehr/healthie/allergy.ts
  • packages/core/src/external/ehr/healthie/index.ts
🧠 Learnings (14)
📓 Common learnings
Learnt from: leite08
PR: metriport/metriport#0
File: :0-0
Timestamp: 2025-03-05T18:43:30.389Z
Learning: For backmerge PRs at metriport/metriport, only verify two things: (1) that the source branch is `master` and destination branch is `develop`, and (2) that there's a link to at least one PR (usually a "patch" PR) in the description. No need for detailed review comments or updates to the PR description unless there's an issue with these criteria.
Learnt from: leite08
PR: metriport/metriport#3611
File: packages/utils/src/fhir-converter/s3-to-lambda.ts:29-47
Timestamp: 2025-04-05T16:02:02.517Z
Learning: For release PRs (where head branch is `develop` and base branch is `master`), don't suggest code changes as these have already been reviewed in previous PRs. Instead, focus only on checking if the PR description follows the template and practices, and if the PR is pointing to the correct base branch (`master`).
Learnt from: lucasdellabella
PR: metriport/metriport#3907
File: packages/terminology/src/seed/seed-ndc-from-fda.ts:91-113
Timestamp: 2025-05-28T05:28:26.896Z
Learning: On PRs with "release" in the title, only provide very high priority feedback and avoid lower priority suggestions like refactoring or optimization improvements.
Learnt from: leite08
PR: metriport/metriport#3749
File: packages/core/src/command/patient-import/record/create-headers-file.ts:16-27
Timestamp: 2025-04-28T22:57:36.763Z
Learning: Focus improvement suggestions on feature branches rather than release PRs. Release PRs should be treated with higher caution as they're focused on getting tested code into production.
Learnt from: thomasyopes
PR: metriport/metriport#3466
File: packages/api/src/routes/ehr/elation/chart.ts:20-37
Timestamp: 2025-03-17T15:30:34.647Z
Learning: The request body parsing in packages/api/src/routes/ehr/elation/chart.ts is tracked with TODO referencing issue #2170 and will be handled in a separate PR, not in PR #3466.
Learnt from: lucasdellabella
PR: metriport/metriport#0
File: :0-0
Timestamp: 2025-03-14T13:44:44.651Z
Learning: Avoid adding AI-generated summaries to PRs with "RELEASE" in the title.
Learnt from: thomasyopes
PR: metriport/metriport#3891
File: packages/api/src/routes/internal/ehr/patient.ts:142-142
Timestamp: 2025-06-20T15:35:00.546Z
Learning: In the EHR resource diff contribution system, there are no "invalid" resource types. The system is designed to gracefully handle any resource type string by attempting to find a corresponding bundle, and if no bundle exists for that resource type, it will simply exit early rather than throwing an error.
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: keshavsaharia
PR: metriport/metriport#4045
File: packages/core/src/external/surescripts/fhir/coverage.ts:0-0
Timestamp: 2025-06-18T18:34:10.489Z
Learning: Coverage resources in Surescripts FHIR conversion are currently excluded from bundles to prevent skewing data lift metrics. The team plans to examine available insurance data thoroughly before including properly structured Coverage resources with mandatory FHIR R4 elements like beneficiary and payor references.
Learnt from: lucasdellabella
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/resource-diff/steps/start/ehr-start-resource-diff-local.ts:0-0
Timestamp: 2025-04-21T03:47:54.332Z
Learning: In the EHR resource diff implementation, bundles should always have an `entry` property, and code should be allowed to throw if `entry` is missing rather than using null-coalescing operators, as this represents an unexpected state that should be caught and addressed.
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/shared/src/interface/external/ehr/athenahealth/vaccine.ts:4-4
Timestamp: 2025-06-06T16:45:21.766Z
Learning: In Athenahealth EHR integration schemas, property names like "vaccineids" are intentionally preserved to match the external API response format since responses are returned directly without internal transformation or usage.
Learnt from: leite08
PR: metriport/metriport#3940
File: packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts:82-86
Timestamp: 2025-05-31T21:58:28.502Z
Learning: In packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts, the mutable array operations using push() on resourcesMutable and hydratedMutable (lines 82-86 and 100-103) have been explicitly accepted as exceptions to the immutability guidelines after previous discussion.
Learnt from: RamilGaripov
PR: metriport/metriport#3675
File: packages/core/src/command/hl7v2-subscriptions/hl7v2-to-fhir-converter.ts:25-27
Timestamp: 2025-04-18T00:33:09.393Z
Learning: The limited set of HL7 message types (currently only "A01" and "A03") in packages/core/src/command/hl7v2-subscriptions/hl7v2-to-fhir-converter.ts is intentional. The team plans to expand support for additional message types incrementally as they learn to process other types.
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/resource-diff/utils.ts:0-0
Timestamp: 2025-04-17T21:27:11.591Z
Learning: For the function `getSupportedResources` in resource-diff utils, returning an empty array for unsupported EHR sources is preferred over throwing an error, as it allows the code to gracefully handle unsupported sources without disruption.
Learnt from: thomasyopes
PR: metriport/metriport#4000
File: packages/core/src/external/ehr/athenahealth/index.ts:504-507
Timestamp: 2025-06-11T21:39:26.805Z
Learning: In AthenaHealth write-back (`packages/core/src/external/ehr/athenahealth/index.ts`), only the condition statuses “relapse” and “recurrence” are currently mapped to AthenaHealth problem statuses (“CHRONIC”); other FHIR clinicalStatus values (e.g., “active”, “resolved”, “inactive”, “remission”) are not yet supported.
packages/core/src/external/ehr/command/get-bundle-by-resource-type.ts (16)
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:27-49
Timestamp: 2025-05-28T19:22:09.281Z
Learning: In packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:0-0
Timestamp: 2025-05-28T19:20:47.442Z
Learning: In packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/canvas/index.ts:451-469
Timestamp: 2025-04-21T17:07:30.574Z
Learning: The `getMetriportOnlyBundleByResourceType` method in CanvasApi returns `Promise<Bundle | undefined>` because the Metriport-only bundle is a computed artifact that may not exist yet. In contrast, `getBundleByResourceType` returns `Promise<Bundle>` because it can always fetch from the EHR API if the S3 cached bundle doesn't exist.
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.
Learnt from: keshavsaharia
PR: metriport/metriport#4045
File: packages/core/src/external/surescripts/fhir/shared.ts:87-93
Timestamp: 2025-06-18T18:50:40.968Z
Learning: The `getResourceFromResourceMap` function in `packages/core/src/external/surescripts/fhir/shared.ts` works correctly as implemented. The comparison `resourceValue === resourceMap[key]` where `resourceValue = resource[key]` is intentional and functions as designed, despite appearing to compare different types.
Learnt from: thomasyopes
PR: metriport/metriport#4061
File: packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/run-job.ts:34-47
Timestamp: 2025-06-19T22:44:49.393Z
Learning: In packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/run-job.ts, the team prefers to keep refreshEhrBundles operations grouped using fire-and-forget pattern rather than awaiting all operations with Promise.allSettled(). This allows individual refresh operations to run independently without blocking the job runner.
Learnt from: lucasdellabella
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/resource-diff/steps/start/ehr-start-resource-diff-local.ts:0-0
Timestamp: 2025-04-21T03:47:54.332Z
Learning: In the EHR resource diff implementation, bundles should always have an `entry` property, and code should be allowed to throw if `entry` is missing rather than using null-coalescing operators, as this represents an unexpected state that should be caught and addressed.
Learnt from: thomasyopes
PR: metriport/metriport#3788
File: packages/api/src/external/ehr/shared/utils/bundle.ts:83-93
Timestamp: 2025-05-08T19:41:36.533Z
Learning: In the Metriport codebase, the team prefers to let errors bubble up naturally in some cases rather than adding explicit error handling at every layer, as demonstrated in the refreshEhrBundle function in the bundle.ts file.
Learnt from: thomasyopes
PR: metriport/metriport#3891
File: packages/api/src/routes/internal/ehr/patient.ts:142-142
Timestamp: 2025-06-20T15:35:00.546Z
Learning: In the EHR resource diff contribution system, there are no "invalid" resource types. The system is designed to gracefully handle any resource type string by attempting to find a corresponding bundle, and if no bundle exists for that resource type, it will simply exit early rather than throwing an error.
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: thomasyopes
PR: metriport/metriport#4090
File: packages/core/src/command/conversion-fhir/conversion-fhir-cloud.ts:30-30
Timestamp: 2025-06-25T01:55:42.627Z
Learning: In packages/core/src/command/conversion-fhir/conversion-fhir-cloud.ts, the FHIR converter Lambda endpoint is controlled by the team and guaranteed to return valid JSON in the expected Bundle<Resource> format, so JSON.parse() error handling and type validation are not necessary for this specific endpoint.
Learnt from: thomasyopes
PR: metriport/metriport#3891
File: packages/core/src/external/ehr/canvas/index.ts:817-823
Timestamp: 2025-05-30T13:40:56.976Z
Learning: In the Canvas API, both resource types from `supportedCanvasResources` and `supportedCanvasResourcesById` can be fetched by resource ID using the `getResourceBundleByResourceId` method. The validation logic should allow both types: `if (!isSupportedCanvasResource(resourceType) && !isSupportedCanvasResourceById(resourceType))`.
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/resource-diff/utils.ts:0-0
Timestamp: 2025-04-17T21:27:11.591Z
Learning: For the function `getSupportedResources` in resource-diff utils, returning an empty array for unsupported EHR sources is preferred over throwing an error, as it allows the code to gracefully handle unsupported sources without disruption.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type.ts:0-0
Timestamp: 2025-05-28T19:21:01.265Z
Learning: For EHR bundle and appointment handlers, the environment property should remain as a basic string type rather than a typed enum because different EHR systems (Athena, Canvas, Elation, Healthie) may have different environment naming conventions beyond the typical prod/staging/sandbox/local pattern.
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/api/src/external/ehr/canvas/command/bundle/fetch-resource-diff-bundle.ts:59-74
Timestamp: 2025-04-23T18:59:21.348Z
Learning: In the Canvas resource diff bundle fetching function, sequential processing (for loop with await) is preferred over parallel processing (Promise.all) for resource fetching to avoid potential load issues if the resource type list grows large, even though it would be slower.
Learnt from: thomasyopes
PR: metriport/metriport#3709
File: packages/api/src/external/ehr/canvas/command/bundle/fetch-ehr-bundle.ts:63-72
Timestamp: 2025-04-23T21:19:02.589Z
Learning: In the metriport codebase, factory functions like `fetchCanvasBundle` in the Canvas EHR subsystem intentionally let errors bubble up to the caller rather than handling them at the factory function level.
packages/api/src/external/ehr/shared/command/bundle/contribute-resource-diff-bundle.ts (17)
Learnt from: lucasdellabella
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/resource-diff/steps/start/ehr-start-resource-diff-local.ts:0-0
Timestamp: 2025-04-21T03:47:54.332Z
Learning: In the EHR resource diff implementation, bundles should always have an `entry` property, and code should be allowed to throw if `entry` is missing rather than using null-coalescing operators, as this represents an unexpected state that should be caught and addressed.
Learnt from: thomasyopes
PR: metriport/metriport#4061
File: packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/run-job.ts:34-47
Timestamp: 2025-06-19T22:44:49.393Z
Learning: In packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/run-job.ts, the team prefers to keep refreshEhrBundles operations grouped using fire-and-forget pattern rather than awaiting all operations with Promise.allSettled(). This allows individual refresh operations to run independently without blocking the job runner.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:27-49
Timestamp: 2025-05-28T19:22:09.281Z
Learning: In packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Learnt from: thomasyopes
PR: metriport/metriport#3891
File: packages/api/src/routes/internal/ehr/patient.ts:142-142
Timestamp: 2025-06-20T15:35:00.546Z
Learning: In the EHR resource diff contribution system, there are no "invalid" resource types. The system is designed to gracefully handle any resource type string by attempting to find a corresponding bundle, and if no bundle exists for that resource type, it will simply exit early rather than throwing an error.
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/resource-diff/utils.ts:0-0
Timestamp: 2025-04-17T21:27:11.591Z
Learning: For the function `getSupportedResources` in resource-diff utils, returning an empty array for unsupported EHR sources is preferred over throwing an error, as it allows the code to gracefully handle unsupported sources without disruption.
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:0-0
Timestamp: 2025-05-28T19:20:47.442Z
Learning: In packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Learnt from: leite08
PR: metriport/metriport#3940
File: packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts:82-86
Timestamp: 2025-05-31T21:58:28.502Z
Learning: In packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts, the mutable array operations using push() on resourcesMutable and hydratedMutable (lines 82-86 and 100-103) have been explicitly accepted as exceptions to the immutability guidelines after previous discussion.
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: lucasdellabella
PR: metriport/metriport#3907
File: packages/core/src/external/fhir/adt-encounters.ts:118-143
Timestamp: 2025-05-28T02:32:27.527Z
Learning: In packages/core/src/external/fhir/adt-encounters.ts, conversion bundles stored by saveAdtConversionBundle do not require version ID assertions or versioning, unlike the sourced encounter data stored by putAdtSourcedEncounter which does require versionId validation.
Learnt from: thomasyopes
PR: metriport/metriport#3788
File: packages/api/src/external/ehr/shared/utils/bundle.ts:83-93
Timestamp: 2025-05-08T19:41:36.533Z
Learning: In the Metriport codebase, the team prefers to let errors bubble up naturally in some cases rather than adding explicit error handling at every layer, as demonstrated in the refreshEhrBundle function in the bundle.ts file.
Learnt from: RamilGaripov
PR: metriport/metriport#3997
File: packages/api/src/routes/internal/ehr/job.ts:33-34
Timestamp: 2025-06-17T15:01:20.015Z
Learning: In the EHR route handlers under packages/api/src/routes/internal/ehr/, the ehrId parameter is moved from req.params to req.query by the processEhrId middleware before reaching the route handlers, so handlers should use getFromQueryOrFail("ehrId", req) not getFrom("params").orFail("ehrId", req).
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/canvas/index.ts:451-469
Timestamp: 2025-04-21T17:07:30.574Z
Learning: The `getMetriportOnlyBundleByResourceType` method in CanvasApi returns `Promise<Bundle | undefined>` because the Metriport-only bundle is a computed artifact that may not exist yet. In contrast, `getBundleByResourceType` returns `Promise<Bundle>` because it can always fetch from the EHR API if the S3 cached bundle doesn't exist.
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.
Learnt from: lucasdellabella
PR: metriport/metriport#4059
File: packages/core/src/command/hl7-notification/hl7-notification-webhook-sender-direct.ts:228-249
Timestamp: 2025-06-19T20:12:54.135Z
Learning: In the Metriport codebase, when data sources are controlled internally (such as FHIR bundles from their own HL7 to FHIR conversion process), the team opts not to add defensive programming checks, preferring to keep the code cleaner rather than adding redundant safety measures for trusted data sources.
Learnt from: thomasyopes
PR: metriport/metriport#3709
File: packages/api/src/external/ehr/canvas/command/bundle/fetch-ehr-bundle.ts:63-72
Timestamp: 2025-04-23T21:19:02.589Z
Learning: In the metriport codebase, factory functions like `fetchCanvasBundle` in the Canvas EHR subsystem intentionally let errors bubble up to the caller rather than handling them at the factory function level.
Learnt from: thomasyopes
PR: metriport/metriport#3870
File: packages/core/src/external/ehr/bundle/job/create-resource-diff-bundles/steps/compute/ehr-compute-resource-diff-bundles-local.ts:55-91
Timestamp: 2025-05-19T18:24:41.632Z
Learning: In EHR bundles related to resource diff computations, bundle creation operations that are for auditing purposes should not stop the main job flow if they fail. These operations typically use try/catch blocks that log errors without rethrowing them, which is the intended behavior.
packages/core/src/external/ehr/job/create-resource-diff-bundles/shared.ts (13)
Learnt from: thomasyopes
PR: metriport/metriport#4061
File: packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/run-job.ts:34-47
Timestamp: 2025-06-19T22:44:49.393Z
Learning: In packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/run-job.ts, the team prefers to keep refreshEhrBundles operations grouped using fire-and-forget pattern rather than awaiting all operations with Promise.allSettled(). This allows individual refresh operations to run independently without blocking the job runner.
Learnt from: lucasdellabella
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/resource-diff/steps/start/ehr-start-resource-diff-local.ts:0-0
Timestamp: 2025-04-21T03:47:54.332Z
Learning: In the EHR resource diff implementation, bundles should always have an `entry` property, and code should be allowed to throw if `entry` is missing rather than using null-coalescing operators, as this represents an unexpected state that should be caught and addressed.
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/resource-diff/utils.ts:0-0
Timestamp: 2025-04-17T21:27:11.591Z
Learning: For the function `getSupportedResources` in resource-diff utils, returning an empty array for unsupported EHR sources is preferred over throwing an error, as it allows the code to gracefully handle unsupported sources without disruption.
Learnt from: leite08
PR: metriport/metriport#3940
File: packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts:82-86
Timestamp: 2025-05-31T21:58:28.502Z
Learning: In packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts, the mutable array operations using push() on resourcesMutable and hydratedMutable (lines 82-86 and 100-103) have been explicitly accepted as exceptions to the immutability guidelines after previous discussion.
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.
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: thomasyopes
PR: metriport/metriport#3891
File: packages/api/src/routes/internal/ehr/patient.ts:142-142
Timestamp: 2025-06-20T15:35:00.546Z
Learning: In the EHR resource diff contribution system, there are no "invalid" resource types. The system is designed to gracefully handle any resource type string by attempting to find a corresponding bundle, and if no bundle exists for that resource type, it will simply exit early rather than throwing an error.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:0-0
Timestamp: 2025-05-28T19:20:47.442Z
Learning: In packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Learnt from: thomasyopes
PR: metriport/metriport#3883
File: packages/core/src/external/ehr/athenahealth/index.ts:0-0
Timestamp: 2025-06-04T12:48:50.168Z
Learning: When arrays contain overlapping values (like supportedAthenaHealthResources and scopes in AthenaHealth), derive one from the other programmatically using spread syntax to prevent divergence when lists change. Use a pattern like `const derivedArray = [...baseArray, ...additionalItems]` to maintain consistency.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:27-49
Timestamp: 2025-05-28T19:22:09.281Z
Learning: In packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/canvas/index.ts:451-469
Timestamp: 2025-04-21T17:07:30.574Z
Learning: The `getMetriportOnlyBundleByResourceType` method in CanvasApi returns `Promise<Bundle | undefined>` because the Metriport-only bundle is a computed artifact that may not exist yet. In contrast, `getBundleByResourceType` returns `Promise<Bundle>` because it can always fetch from the EHR API if the S3 cached bundle doesn't exist.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type.ts:0-0
Timestamp: 2025-05-28T19:21:01.265Z
Learning: For EHR bundle and appointment handlers, the environment property should remain as a basic string type rather than a typed enum because different EHR systems (Athena, Canvas, Elation, Healthie) may have different environment naming conventions beyond the typical prod/staging/sandbox/local pattern.
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/api/src/external/ehr/canvas/command/bundle/fetch-resource-diff-bundle.ts:59-74
Timestamp: 2025-04-23T18:59:21.348Z
Learning: In the Canvas resource diff bundle fetching function, sequential processing (for loop with await) is preferred over parallel processing (Promise.all) for resource fetching to avoid potential load issues if the resource type list grows large, even though it would be slower.
packages/shared/src/interface/external/ehr/healthie/index.ts (13)
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.
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: RamilGaripov
PR: metriport/metriport#3676
File: packages/core/src/command/hl7v2-subscriptions/hl7v2-to-fhir-conversion/shared.ts:1-10
Timestamp: 2025-04-16T00:25:25.196Z
Learning: The circular dependency between shared.ts (importing getPatientIdsOrFail) and adt/utils.ts (using unpackPidFieldOrFail) will be addressed in a follow-up PR.
Learnt from: RamilGaripov
PR: metriport/metriport#3976
File: packages/api/src/routes/medical/patient.ts:541-543
Timestamp: 2025-06-18T21:05:22.256Z
Learning: In packages/api/src/routes/medical/patient.ts, inline schema definitions like cohortIdSchema are acceptable and don't need to be moved to separate schema files when the user prefers to keep them inline.
Learnt from: keshavsaharia
PR: metriport/metriport#4075
File: packages/core/src/external/surescripts/fhir/medication-request.ts:76-83
Timestamp: 2025-06-25T18:42:07.231Z
Learning: In packages/core/src/external/surescripts/fhir/medication-request.ts, the getDispenseNote and getDosageInstruction functions are intentionally identical because the dashboard requires both the note and dosageInstruction fields of MedicationRequest to be populated with detail.directions for proper note display functionality.
Learnt from: lucasdellabella
PR: metriport/metriport#3866
File: packages/api/src/routes/internal/medical/organization.ts:95-98
Timestamp: 2025-05-27T15:54:47.774Z
Learning: The conversion of the GET `/internal/organization` endpoint from returning a single organization to returning an array of organizations (batch retrieval) in `packages/api/src/routes/internal/medical/organization.ts` was an intentional breaking change planned by the team.
Learnt from: thomasyopes
PR: metriport/metriport#4000
File: packages/core/src/external/ehr/athenahealth/index.ts:504-507
Timestamp: 2025-06-11T21:39:26.805Z
Learning: In AthenaHealth write-back (`packages/core/src/external/ehr/athenahealth/index.ts`), only the condition statuses “relapse” and “recurrence” are currently mapped to AthenaHealth problem statuses (“CHRONIC”); other FHIR clinicalStatus values (e.g., “active”, “resolved”, “inactive”, “remission”) are not yet supported.
Learnt from: leite08
PR: metriport/metriport#3463
File: packages/api-sdk/src/medical/models/patient.ts:1-1
Timestamp: 2025-03-19T13:58:17.253Z
Learning: When changes are made to SDK packages (`api-sdk`, `commonwell-sdk`, `carequality-sdk`) or `packages/shared` in the Metriport codebase, alpha versions need to be published to NPM before merging the PR.
Learnt from: lucasdellabella
PR: metriport/metriport#4098
File: packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts:10-22
Timestamp: 2025-06-27T01:50:14.227Z
Learning: In packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts, the patient fields patientData.firstName, patientData.lastName, and patientData.dob are guaranteed to be non-nullable values, so defensive null/undefined checks are not needed when accessing these fields.
Learnt from: keshavsaharia
PR: metriport/metriport#3885
File: packages/core/src/external/sftp/surescripts/client.ts:1-134
Timestamp: 2025-05-28T19:23:20.179Z
Learning: In packages/core/src/external/sftp/surescripts/client.ts, the standalone getPatientLoadFileName function intentionally omits the transmission ID from the filename, which differs from the class method getPatientLoadFileName. This difference in filename generation is expected behavior.
Learnt from: leite08
PR: metriport/metriport#3659
File: packages/utils/src/facility/make-npi.ts:1-1
Timestamp: 2025-04-12T15:09:43.545Z
Learning: Importing from test directories (e.g., "__tests__") is acceptable for utility scripts in this codebase when using the npm workspace setup, as these scripts are not part of the production code.
Learnt from: leite08
PR: metriport/metriport#3648
File: packages/utils/src/shared/patient-create.ts:35-53
Timestamp: 2025-04-10T17:30:30.368Z
Learning: The function `mergePatients` in the patient-create.ts file is intentionally designed to take all properties from the first patient (p1) and only update address and contact fields, as the system supports duplicated patients specifically to allow multiple addresses across different records.
Learnt from: leite08
PR: metriport/metriport#4034
File: packages/core/src/command/patient-import/patient-or-record-failed.ts:19-30
Timestamp: 2025-06-16T17:03:23.069Z
Learning: In patient import error handling functions like setPatientOrRecordFailed, the team prefers Promise.all over Promise.allSettled to ensure atomic all-or-nothing behavior - if either the job update or patient record update fails, the entire operation should fail rather than allowing partial success.
packages/core/src/external/ehr/healthie/command/get-bundle-by-resource-type.ts (12)
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/canvas/index.ts:451-469
Timestamp: 2025-04-21T17:07:30.574Z
Learning: The `getMetriportOnlyBundleByResourceType` method in CanvasApi returns `Promise<Bundle | undefined>` because the Metriport-only bundle is a computed artifact that may not exist yet. In contrast, `getBundleByResourceType` returns `Promise<Bundle>` because it can always fetch from the EHR API if the S3 cached bundle doesn't exist.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:27-49
Timestamp: 2025-05-28T19:22:09.281Z
Learning: In packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:0-0
Timestamp: 2025-05-28T19:20:47.442Z
Learning: In packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Learnt from: thomasyopes
PR: metriport/metriport#4061
File: packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/run-job.ts:34-47
Timestamp: 2025-06-19T22:44:49.393Z
Learning: In packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/run-job.ts, the team prefers to keep refreshEhrBundles operations grouped using fire-and-forget pattern rather than awaiting all operations with Promise.allSettled(). This allows individual refresh operations to run independently without blocking the job runner.
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.
Learnt from: thomasyopes
PR: metriport/metriport#4090
File: packages/core/src/command/conversion-fhir/conversion-fhir-cloud.ts:30-30
Timestamp: 2025-06-25T01:55:42.627Z
Learning: In packages/core/src/command/conversion-fhir/conversion-fhir-cloud.ts, the FHIR converter Lambda endpoint is controlled by the team and guaranteed to return valid JSON in the expected Bundle<Resource> format, so JSON.parse() error handling and type validation are not necessary for this specific endpoint.
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: thomasyopes
PR: metriport/metriport#3891
File: packages/api/src/routes/internal/ehr/patient.ts:142-142
Timestamp: 2025-06-20T15:35:00.546Z
Learning: In the EHR resource diff contribution system, there are no "invalid" resource types. The system is designed to gracefully handle any resource type string by attempting to find a corresponding bundle, and if no bundle exists for that resource type, it will simply exit early rather than throwing an error.
Learnt from: thomasyopes
PR: metriport/metriport#3891
File: packages/core/src/external/ehr/canvas/index.ts:817-823
Timestamp: 2025-05-30T13:40:56.976Z
Learning: In the Canvas API, both resource types from `supportedCanvasResources` and `supportedCanvasResourcesById` can be fetched by resource ID using the `getResourceBundleByResourceId` method. The validation logic should allow both types: `if (!isSupportedCanvasResource(resourceType) && !isSupportedCanvasResourceById(resourceType))`.
Learnt from: keshavsaharia
PR: metriport/metriport#4045
File: packages/core/src/external/surescripts/fhir/shared.ts:87-93
Timestamp: 2025-06-18T18:50:40.968Z
Learning: The `getResourceFromResourceMap` function in `packages/core/src/external/surescripts/fhir/shared.ts` works correctly as implemented. The comparison `resourceValue === resourceMap[key]` where `resourceValue = resource[key]` is intentional and functions as designed, despite appearing to compare different types.
Learnt from: thomasyopes
PR: metriport/metriport#3788
File: packages/api/src/external/ehr/shared/utils/bundle.ts:83-93
Timestamp: 2025-05-08T19:41:36.533Z
Learning: In the Metriport codebase, the team prefers to let errors bubble up naturally in some cases rather than adding explicit error handling at every layer, as demonstrated in the refreshEhrBundle function in the bundle.ts file.
Learnt from: thomasyopes
PR: metriport/metriport#3709
File: packages/api/src/external/ehr/canvas/command/bundle/fetch-resource-diff-bundle.ts:62-73
Timestamp: 2025-04-23T21:19:08.443Z
Learning: In the metriport codebase, factory functions like `fetchResourceDiffBundle` intentionally let errors bubble up to the caller rather than handling them at the factory function level. This is a consistent pattern across factory implementations.
packages/shared/src/interface/external/ehr/healthie/medication.ts (10)
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.
Learnt from: RamilGaripov
PR: metriport/metriport#3976
File: packages/api/src/routes/medical/patient.ts:541-543
Timestamp: 2025-06-18T21:05:22.256Z
Learning: In packages/api/src/routes/medical/patient.ts, inline schema definitions like cohortIdSchema are acceptable and don't need to be moved to separate schema files when the user prefers to keep them inline.
Learnt from: keshavsaharia
PR: metriport/metriport#4075
File: packages/core/src/external/surescripts/fhir/medication-request.ts:76-83
Timestamp: 2025-06-25T18:42:07.231Z
Learning: In packages/core/src/external/surescripts/fhir/medication-request.ts, the getDispenseNote and getDosageInstruction functions are intentionally identical because the dashboard requires both the note and dosageInstruction fields of MedicationRequest to be populated with detail.directions for proper note display functionality.
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: keshavsaharia
PR: metriport/metriport#3885
File: packages/core/src/external/surescripts/schema/load.ts:65-71
Timestamp: 2025-05-30T03:42:53.380Z
Learning: In Surescripts schema files like `packages/core/src/external/surescripts/schema/load.ts`, the `key` property in field definitions is only used for direct one-to-one field mappings. When multiple fields are derived from the same source property but with different transformations (like extracting date vs. time portions), they should not have `key` properties as they represent transformations rather than direct mappings.
Learnt from: lucasdellabella
PR: metriport/metriport#4098
File: packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts:10-22
Timestamp: 2025-06-27T01:50:14.227Z
Learning: In packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts, the patient fields patientData.firstName, patientData.lastName, and patientData.dob are guaranteed to be non-nullable values, so defensive null/undefined checks are not needed when accessing these fields.
Learnt from: thomasyopes
PR: metriport/metriport#3936
File: packages/core/src/external/ehr/athenahealth/index.ts:472-482
Timestamp: 2025-06-06T15:37:44.571Z
Learning: In AthenaHealth medication creation, even if medication statements have the same start/stop dates, they should not be deduplicated because there may be relevant differences beyond dates (dosage, administration routes, prescriber info, etc.) that make each statement unique and worth creating separately.
Learnt from: RamilGaripov
PR: metriport/metriport#3676
File: packages/core/src/command/hl7v2-subscriptions/hl7v2-to-fhir-conversion/shared.ts:1-10
Timestamp: 2025-04-16T00:25:25.196Z
Learning: The circular dependency between shared.ts (importing getPatientIdsOrFail) and adt/utils.ts (using unpackPidFieldOrFail) will be addressed in a follow-up PR.
Learnt from: keshavsaharia
PR: metriport/metriport#3885
File: packages/core/src/external/surescripts/client.ts:0-0
Timestamp: 2025-05-30T01:09:55.013Z
Learning: In packages/core/src/external/surescripts/client.ts, the Surescripts date formatting should use local time according to their documentation ("message-date-must-be-local"), which means buildDayjs() cannot be used since it defaults to UTC. The specific use case for transmission date formatting requires dayjs to be used directly to preserve local time behavior.
Learnt from: keshavsaharia
PR: metriport/metriport#4045
File: packages/shared/src/interface/external/surescripts/dea-schedule.ts:1-3
Timestamp: 2025-06-18T18:14:48.486Z
Learning: The `getDeaScheduleName` function in packages/shared/src/interface/external/surescripts/dea-schedule.ts is designed to accept any string (not just valid DEAScheduleCode values) and return undefined for unknown codes. This flexible design allows it to handle potentially invalid data from external sources gracefully.
packages/shared/src/interface/external/ehr/healthie/lab.ts (10)
Learnt from: RamilGaripov
PR: metriport/metriport#3976
File: packages/api/src/routes/medical/patient.ts:541-543
Timestamp: 2025-06-18T21:05:22.256Z
Learning: In packages/api/src/routes/medical/patient.ts, inline schema definitions like cohortIdSchema are acceptable and don't need to be moved to separate schema files when the user prefers to keep them inline.
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: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.
Learnt from: keshavsaharia
PR: metriport/metriport#3885
File: packages/core/src/external/surescripts/schema/load.ts:65-71
Timestamp: 2025-05-30T03:42:53.380Z
Learning: In Surescripts schema files like `packages/core/src/external/surescripts/schema/load.ts`, the `key` property in field definitions is only used for direct one-to-one field mappings. When multiple fields are derived from the same source property but with different transformations (like extracting date vs. time portions), they should not have `key` properties as they represent transformations rather than direct mappings.
Learnt from: lucasdellabella
PR: metriport/metriport#4098
File: packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts:10-22
Timestamp: 2025-06-27T01:50:14.227Z
Learning: In packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts, the patient fields patientData.firstName, patientData.lastName, and patientData.dob are guaranteed to be non-nullable values, so defensive null/undefined checks are not needed when accessing these fields.
Learnt from: RamilGaripov
PR: metriport/metriport#3676
File: packages/core/src/command/hl7v2-subscriptions/hl7v2-to-fhir-conversion/shared.ts:1-10
Timestamp: 2025-04-16T00:25:25.196Z
Learning: The circular dependency between shared.ts (importing getPatientIdsOrFail) and adt/utils.ts (using unpackPidFieldOrFail) will be addressed in a follow-up PR.
Learnt from: thomasyopes
PR: metriport/metriport#3709
File: packages/shared/src/interface/external/ehr/fhir-resource.ts:4-10
Timestamp: 2025-04-23T21:22:35.000Z
Learning: The team prefers a more general validation approach for FHIR resource types with `z.string() as z.ZodType<SupportedResourceType>` and handles specific resource type validation elsewhere in the app code rather than using strict Zod enum/union constraints.
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/shared/src/interface/external/ehr/athenahealth/vaccine.ts:4-4
Timestamp: 2025-06-06T16:45:21.766Z
Learning: In Athenahealth EHR integration schemas, property names like "vaccineids" are intentionally preserved to match the external API response format since responses are returned directly without internal transformation or usage.
Learnt from: thomasyopes
PR: metriport/metriport#3466
File: packages/api/src/routes/ehr/elation/chart.ts:20-37
Timestamp: 2025-03-17T15:30:34.647Z
Learning: The request body parsing in packages/api/src/routes/ehr/elation/chart.ts is tracked with TODO referencing issue #2170 and will be handled in a separate PR, not in PR #3466.
Learnt from: leite08
PR: metriport/metriport#3463
File: packages/api/src/routes/internal/medical/patient-settings.ts:31-49
Timestamp: 2025-03-19T01:11:01.406Z
Learning: In the Metriport codebase, Zod schema validation errors in routes are intentionally allowed to propagate to the central error handler (packages/api/src/routes/helpers/default-error-handler.ts) rather than being caught with try/catch blocks in individual route handlers. The error handler automatically processes ZodErrors and returns a 400 Bad Request response with formatted validation details.
packages/core/src/external/ehr/bundle/bundle-shared.ts (16)
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/resource-diff/utils.ts:0-0
Timestamp: 2025-04-17T21:27:11.591Z
Learning: For the function `getSupportedResources` in resource-diff utils, returning an empty array for unsupported EHR sources is preferred over throwing an error, as it allows the code to gracefully handle unsupported sources without disruption.
Learnt from: lucasdellabella
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/resource-diff/steps/start/ehr-start-resource-diff-local.ts:0-0
Timestamp: 2025-04-21T03:47:54.332Z
Learning: In the EHR resource diff implementation, bundles should always have an `entry` property, and code should be allowed to throw if `entry` is missing rather than using null-coalescing operators, as this represents an unexpected state that should be caught and addressed.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:0-0
Timestamp: 2025-05-28T19:20:47.442Z
Learning: In packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:27-49
Timestamp: 2025-05-28T19:22:09.281Z
Learning: In packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Learnt from: thomasyopes
PR: metriport/metriport#4061
File: packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/run-job.ts:34-47
Timestamp: 2025-06-19T22:44:49.393Z
Learning: In packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/run-job.ts, the team prefers to keep refreshEhrBundles operations grouped using fire-and-forget pattern rather than awaiting all operations with Promise.allSettled(). This allows individual refresh operations to run independently without blocking the job runner.
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#3940
File: packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts:82-86
Timestamp: 2025-05-31T21:58:28.502Z
Learning: In packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts, the mutable array operations using push() on resourcesMutable and hydratedMutable (lines 82-86 and 100-103) have been explicitly accepted as exceptions to the immutability guidelines after previous discussion.
Learnt from: thomasyopes
PR: metriport/metriport#3891
File: packages/api/src/routes/internal/ehr/patient.ts:142-142
Timestamp: 2025-06-20T15:35:00.546Z
Learning: In the EHR resource diff contribution system, there are no "invalid" resource types. The system is designed to gracefully handle any resource type string by attempting to find a corresponding bundle, and if no bundle exists for that resource type, it will simply exit early rather than throwing an error.
Learnt from: keshavsaharia
PR: metriport/metriport#4045
File: packages/core/src/external/surescripts/fhir/coverage.ts:0-0
Timestamp: 2025-06-18T18:34:10.489Z
Learning: Coverage resources in Surescripts FHIR conversion are currently excluded from bundles to prevent skewing data lift metrics. The team plans to examine available insurance data thoroughly before including properly structured Coverage resources with mandatory FHIR R4 elements like beneficiary and payor references.
Learnt from: thomasyopes
PR: metriport/metriport#3883
File: packages/core/src/external/ehr/athenahealth/index.ts:0-0
Timestamp: 2025-06-04T12:48:50.168Z
Learning: When arrays contain overlapping values (like supportedAthenaHealthResources and scopes in AthenaHealth), derive one from the other programmatically using spread syntax to prevent divergence when lists change. Use a pattern like `const derivedArray = [...baseArray, ...additionalItems]` to maintain consistency.
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/canvas/index.ts:451-469
Timestamp: 2025-04-21T17:07:30.574Z
Learning: The `getMetriportOnlyBundleByResourceType` method in CanvasApi returns `Promise<Bundle | undefined>` because the Metriport-only bundle is a computed artifact that may not exist yet. In contrast, `getBundleByResourceType` returns `Promise<Bundle>` because it can always fetch from the EHR API if the S3 cached bundle doesn't exist.
Learnt from: thomasyopes
PR: metriport/metriport#3891
File: packages/core/src/external/ehr/canvas/index.ts:817-823
Timestamp: 2025-05-30T13:40:56.976Z
Learning: In the Canvas API, both resource types from `supportedCanvasResources` and `supportedCanvasResourcesById` can be fetched by resource ID using the `getResourceBundleByResourceId` method. The validation logic should allow both types: `if (!isSupportedCanvasResource(resourceType) && !isSupportedCanvasResourceById(resourceType))`.
Learnt from: leite08
PR: metriport/metriport#3859
File: packages/utils/src/consolidated/check-patient-consolidated.ts:28-32
Timestamp: 2025-05-26T16:24:10.245Z
Learning: For utility scripts in the packages/utils directory, developers are expected to update the main constants at the top of the file (like bundleFilePath, cxId, patientId) rather than implementing command-line argument parsing or environment variable reading. This is the preferred pattern for configuring utility scripts in this codebase.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type.ts:0-0
Timestamp: 2025-05-28T19:21:01.265Z
Learning: For EHR bundle and appointment handlers, the environment property should remain as a basic string type rather than a typed enum because different EHR systems (Athena, Canvas, Elation, Healthie) may have different environment naming conventions beyond the typical prod/staging/sandbox/local pattern.
Learnt from: thomasyopes
PR: metriport/metriport#3771
File: packages/api/src/routes/internal/ehr/healthie/secret-key.ts:24-31
Timestamp: 2025-05-01T16:11:28.575Z
Learning: The function `getHealthieSecretKeyInfo` in the Healthie EHR integration throws appropriate MetriportErrors when required data is missing, so it will never return undefined or an empty object.
packages/shared/src/interface/external/ehr/healthie/condition.ts (7)
Learnt from: RamilGaripov
PR: metriport/metriport#3976
File: packages/api/src/routes/medical/patient.ts:541-543
Timestamp: 2025-06-18T21:05:22.256Z
Learning: In packages/api/src/routes/medical/patient.ts, inline schema definitions like cohortIdSchema are acceptable and don't need to be moved to separate schema files when the user prefers to keep them inline.
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: thomasyopes
PR: metriport/metriport#4000
File: packages/core/src/external/ehr/athenahealth/index.ts:504-507
Timestamp: 2025-06-11T21:39:26.805Z
Learning: In AthenaHealth write-back (`packages/core/src/external/ehr/athenahealth/index.ts`), only the condition statuses “relapse” and “recurrence” are currently mapped to AthenaHealth problem statuses (“CHRONIC”); other FHIR clinicalStatus values (e.g., “active”, “resolved”, “inactive”, “remission”) are not yet supported.
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.
Learnt from: lucasdellabella
PR: metriport/metriport#4098
File: packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts:10-22
Timestamp: 2025-06-27T01:50:14.227Z
Learning: In packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts, the patient fields patientData.firstName, patientData.lastName, and patientData.dob are guaranteed to be non-nullable values, so defensive null/undefined checks are not needed when accessing these fields.
Learnt from: RamilGaripov
PR: metriport/metriport#3676
File: packages/core/src/command/hl7v2-subscriptions/hl7v2-to-fhir-conversion/shared.ts:1-10
Timestamp: 2025-04-16T00:25:25.196Z
Learning: The circular dependency between shared.ts (importing getPatientIdsOrFail) and adt/utils.ts (using unpackPidFieldOrFail) will be addressed in a follow-up PR.
Learnt from: keshavsaharia
PR: metriport/metriport#3885
File: packages/core/src/external/surescripts/schema/load.ts:65-71
Timestamp: 2025-05-30T03:42:53.380Z
Learning: In Surescripts schema files like `packages/core/src/external/surescripts/schema/load.ts`, the `key` property in field definitions is only used for direct one-to-one field mappings. When multiple fields are derived from the same source property but with different transformations (like extracting date vs. time portions), they should not have `key` properties as they represent transformations rather than direct mappings.
packages/shared/src/interface/external/ehr/healthie/immunization.ts (8)
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.
Learnt from: RamilGaripov
PR: metriport/metriport#3976
File: packages/api/src/routes/medical/patient.ts:541-543
Timestamp: 2025-06-18T21:05:22.256Z
Learning: In packages/api/src/routes/medical/patient.ts, inline schema definitions like cohortIdSchema are acceptable and don't need to be moved to separate schema files when the user prefers to keep them inline.
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/shared/src/interface/external/ehr/athenahealth/vaccine.ts:4-4
Timestamp: 2025-06-06T16:45:21.766Z
Learning: In Athenahealth EHR integration schemas, property names like "vaccineids" are intentionally preserved to match the external API response format since responses are returned directly without internal transformation or usage.
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: lucasdellabella
PR: metriport/metriport#4098
File: packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts:10-22
Timestamp: 2025-06-27T01:50:14.227Z
Learning: In packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts, the patient fields patientData.firstName, patientData.lastName, and patientData.dob are guaranteed to be non-nullable values, so defensive null/undefined checks are not needed when accessing these fields.
Learnt from: leite08
PR: metriport/metriport#3940
File: packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts:82-86
Timestamp: 2025-05-31T21:58:28.502Z
Learning: In packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts, the mutable array operations using push() on resourcesMutable and hydratedMutable (lines 82-86 and 100-103) have been explicitly accepted as exceptions to the immutability guidelines after previous discussion.
Learnt from: keshavsaharia
PR: metriport/metriport#4099
File: packages/core/src/external/surescripts/fhir/coverage.ts:37-42
Timestamp: 2025-06-26T06:28:31.490Z
Learning: In packages/core/src/external/surescripts/fhir/coverage.ts, the getInsuranceOrganizationReference function doesn't need ID validation because the Organization resources are always created by getInsuranceOrganization which assigns id: uuidv7(), guaranteeing a valid ID is present.
Learnt from: RamilGaripov
PR: metriport/metriport#3676
File: packages/core/src/command/hl7v2-subscriptions/hl7v2-to-fhir-conversion/shared.ts:1-10
Timestamp: 2025-04-16T00:25:25.196Z
Learning: The circular dependency between shared.ts (importing getPatientIdsOrFail) and adt/utils.ts (using unpackPidFieldOrFail) will be addressed in a follow-up PR.
packages/infra/lib/ehr-nested-stack.ts (31)
Learnt from: thomasyopes
PR: metriport/metriport#3709
File: packages/infra/lib/ehr-nested-stack.ts:470-486
Timestamp: 2025-04-23T19:33:45.489Z
Learning: The `refreshEhrBundles` Lambda in the EhrNestedStack uses the API to refresh bundles, rather than accessing the S3 bucket directly. This is why it doesn't need the EHR_BUNDLE_BUCKET_NAME environment variable or direct S3 bucket permissions, unlike other similar Lambdas.
Learnt from: thomasyopes
PR: metriport/metriport#4061
File: packages/infra/lib/jobs/jobs-stack.ts:36-36
Timestamp: 2025-06-19T22:44:38.904Z
Learning: In the jobs infrastructure (packages/infra/lib/jobs/jobs-stack.ts), maxReceiveCount: 1 is intentionally set for the patient job queue to fail fast and send messages to DLQ after a single failure, rather than allowing retries.
Learnt from: thomasyopes
PR: metriport/metriport#4061
File: packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/run-job.ts:34-47
Timestamp: 2025-06-19T22:44:49.393Z
Learning: In packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/run-job.ts, the team prefers to keep refreshEhrBundles operations grouped using fire-and-forget pattern rather than awaiting all operations with Promise.allSettled(). This allows individual refresh operations to run independently without blocking the job runner.
Learnt from: thomasyopes
PR: metriport/metriport#3427
File: packages/core/src/external/ehr/api/sync-patient.ts:16-55
Timestamp: 2025-03-11T20:42:46.516Z
Learning: In the patient synchronization architecture, the flow follows this pattern: (1) `ehr-sync-patient-cloud.ts` sends messages to an SQS queue, (2) the `ehr-sync-patient` Lambda consumes these messages, and (3) the Lambda uses the `syncPatient` function to make the API calls to process the patient data.
Learnt from: leite08
PR: metriport/metriport#3817
File: .github/workflows/deploy-staging.yml:206-214
Timestamp: 2025-05-12T18:29:48.116Z
Learning: In the Metriport CI/CD workflows, the IHE stack deployment is intentionally triggered by general infrastructure changes (infra-lambdas) rather than having its own dedicated change detection, as it needs to stay in sync with other infrastructure components.
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: thomasyopes
PR: metriport/metriport#3608
File: packages/lambdas/src/ehr-compute-resource-diff.ts:29-30
Timestamp: 2025-04-19T13:19:25.570Z
Learning: Avoid logging raw SQS message bodies in EHR-related lambdas as they may contain PHI (Protected Health Information) like lists of healthcare resources that shouldn't be exposed in CloudWatch logs.
Learnt from: leite08
PR: metriport/metriport#3709
File: packages/core/src/external/ehr/bundle/create-resource-diff-bundles/steps/start/ehr-start-resource-diff-bundles-local.ts:18-24
Timestamp: 2025-04-23T21:39:58.678Z
Learning: The instance of `EhrStartResourceDiffBundlesLocal` is created inside the Lambda handler function, ensuring a fresh instance on each invocation with no state leakage between invocations.
Learnt from: lucasdellabella
PR: metriport/metriport#3877
File: packages/infra/lib/hl7-notification-stack/mllp.ts:28-32
Timestamp: 2025-05-20T20:01:07.202Z
Learning: In packages/infra/lib/hl7-notification-stack/mllp.ts, the strict validation check that requires exactly one private subnet is intentional. It's designed to fail loudly and force code changes if subnet configurations change in the future, rather than silently adapting to potentially incompatible infrastructure changes.
Learnt from: leite08
PR: metriport/metriport#3463
File: packages/api-sdk/src/medical/models/patient.ts:1-1
Timestamp: 2025-03-19T13:58:17.253Z
Learning: When changes are made to SDK packages (`api-sdk`, `commonwell-sdk`, `carequality-sdk`) or `packages/shared` in the Metriport codebase, alpha versions need to be published to NPM before merging the PR.
Learnt from: thomasyopes
PR: metriport/metriport#3771
File: packages/core/src/util/sqs.ts:1-4
Timestamp: 2025-05-01T16:10:50.904Z
Learning: In the Metriport codebase, SQS_MESSAGE_BATCH_SIZE constants (SQS_MESSAGE_BATCH_SIZE_FIFO and SQS_MESSAGE_BATCH_SIZE_STANDARD) are used for application-level chunking with the chunk() function before sending individual messages, not for AWS SQS SendMessageBatch API calls. They control parallelism when processing arrays of data, not AWS API batch sizes, so they don't need to match AWS SQS API limits (10 for FIFO, 10,000 for standard).
Learnt from: lucasdellabella
PR: metriport/metriport#3576
File: packages/infra/lib/hl7-notification-webhook-sender-nested-stack.ts:15-16
Timestamp: 2025-04-17T06:25:32.315Z
Learning: Avoid introducing sleep/delay in Lambda functions as it's an anti-pattern. Instead, use AWS platform features like event source's max concurrency to control throttling and processing rates.
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/api/src/external/ehr/canvas/command/bundle/fetch-resource-diff-bundle.ts:59-74
Timestamp: 2025-04-23T18:59:21.348Z
Learning: In the Canvas resource diff bundle fetching function, sequential processing (for loop with await) is preferred over parallel processing (Promise.all) for resource fetching to avoid potential load issues if the resource type list grows large, even though it would be slower.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:0-0
Timestamp: 2025-05-28T19:20:47.442Z
Learning: In packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:27-49
Timestamp: 2025-05-28T19:22:09.281Z
Learning: In packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Learnt from: thomasyopes
PR: metriport/metriport#3870
File: packages/core/src/external/ehr/bundle/job/create-resource-diff-bundles/steps/compute/ehr-compute-resource-diff-bundles-local.ts:55-91
Timestamp: 2025-05-19T18:24:41.632Z
Learning: In EHR bundles related to resource diff computations, bundle creation operations that are for auditing purposes should not stop the main job flow if they fail. These operations typically use try/catch blocks that log errors without rethrowing them, which is the intended behavior.
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/canvas/index.ts:451-469
Timestamp: 2025-04-21T17:07:30.574Z
Learning: The `getMetriportOnlyBundleByResourceType` method in CanvasApi returns `Promise<Bundle | undefined>` because the Metriport-only bundle is a computed artifact that may not exist yet. In contrast, `getBundleByResourceType` returns `Promise<Bundle>` because it can always fetch from the EHR API if the S3 cached bundle doesn't exist.
Learnt from: leite08
PR: metriport/metriport#4043
File: packages/core/src/command/consolidated/consolidated-create.ts:0-0
Timestamp: 2025-06-18T00:18:59.144Z
Learning: In the consolidated bundle creation process (packages/core/src/command/consolidated/consolidated-create.ts), the team prefers strict failure behavior where if any component (including pharmacy resources) fails to be retrieved, the entire consolidation should fail rather than gracefully degrading. This ensures data consistency and prevents incomplete bundles.
Learnt from: thomasyopes
PR: metriport/metriport#3709
File: packages/api/src/external/ehr/canvas/command/bundle/fetch-resource-diff-bundle.ts:62-73
Timestamp: 2025-04-23T21:19:08.443Z
Learning: In the metriport codebase, factory functions like `fetchResourceDiffBundle` intentionally let errors bubble up to the caller rather than handling them at the factory function level. This is a consistent pattern across factory implementations.
Learnt from: thomasyopes
PR: metriport/metriport#4088
File: packages/infra/lib/api-stack/fhir-converter-service.ts:169-183
Timestamp: 2025-06-24T23:24:13.227Z
Learning: For Lambda functions in the FHIR converter service infrastructure, staging and production environments should have matching configuration values (memory size, timeout, etc.) rather than different values per environment.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type.ts:0-0
Timestamp: 2025-05-28T19:21:01.265Z
Learning: For EHR bundle and appointment handlers, the environment property should remain as a basic string type rather than a typed enum because different EHR systems (Athena, Canvas, Elation, Healthie) may have different environment naming conventions beyond the typical prod/staging/sandbox/local pattern.
Learnt from: leite08
PR: metriport/metriport#3469
File: packages/utils/src/s3/list-objects.ts:12-13
Timestamp: 2025-03-14T01:14:58.991Z
Learning: Utility scripts in the `packages/utils/src/s3/` directory intentionally use empty strings for configuration values (like bucket names and prefixes) which are expected to be populated by users before running the script. This is the established pattern for these types of utility files, and we should not suggest changing them to use environment variables or other mechanisms.
Learnt from: thomasyopes
PR: metriport/metriport#3871
File: packages/infra/lib/surescripts-stack.ts:189-189
Timestamp: 2025-05-21T20:57:09.547Z
Learning: When creating AWS S3 buckets with AWS CDK, if the bucketName property is not provided, CDK will generate a default name rather than failing. In the Metriport codebase, properties like bucket names should be made required in type definitions rather than adding runtime validation.
Learnt from: leite08
PR: metriport/metriport#3469
File: packages/utils/src/s3/list-objects.ts:12-13
Timestamp: 2025-03-14T01:14:58.991Z
Learning: In utility scripts under `./packages/utils/src/s3/`, empty string values like `const bucketName = ``; const filePrefix = ``;` are intentional placeholders meant to be filled in by developers before running the script, as documented in the TSDoc comments. These should not be flagged as issues or suggested to be replaced with environment variables.
Learnt from: thomasyopes
PR: metriport/metriport#4090
File: packages/core/src/command/conversion-fhir/conversion-fhir-cloud.ts:30-30
Timestamp: 2025-06-25T01:55:42.627Z
Learning: In packages/core/src/command/conversion-fhir/conversion-fhir-cloud.ts, the FHIR converter Lambda endpoint is controlled by the team and guaranteed to return valid JSON in the expected Bundle<Resource> format, so JSON.parse() error handling and type validation are not necessary for this specific endpoint.
Learnt from: leite08
PR: metriport/metriport#3709
File: packages/core/src/external/ehr/bundle/create-resource-diff-bundles/steps/start/ehr-start-resource-diff-bundles-local.ts:18-24
Timestamp: 2025-04-23T21:39:58.678Z
Learning: In AWS Lambda functions, instances created inside the handler function (not as global variables) are recreated on each invocation, ensuring no state leakage between invocations, as seen with `EhrStartResourceDiffBundlesLocal` in the ehr-start-resource-diff-bundles Lambda.
Learnt from: thomasyopes
PR: metriport/metriport#3572
File: packages/core/src/external/carequality/ihe-gateway-v2/outbound/ihe-gateway-v2-logic.ts:0-0
Timestamp: 2025-04-01T20:10:45.776Z
Learning: In the IHE Gateway V2 implementation, S3 write operations rely on AWS Lambda's built-in error handling infrastructure rather than explicit try-catch blocks in the code.
Learnt from: thomasyopes
PR: metriport/metriport#3771
File: packages/lambdas/src/healthie-link-patient.ts:18-19
Timestamp: 2025-05-01T16:11:56.826Z
Learning: Environment variables that are explicitly set by the team in a controlled manner (like WAIT_TIME_IN_MILLIS in Lambda configurations) don't require additional validation checks as their values are guaranteed to be of the correct type.
Learnt from: lucasdellabella
PR: metriport/metriport#3844
File: packages/infra/lib/hl7-notification-webhook-sender-nested-stack.ts:131-140
Timestamp: 2025-05-15T14:00:12.763Z
Learning: The team prefers to maintain consistent S3 permission patterns across the codebase using grantReadWrite() even when more specific permissions (like grantRead/grantPut) would be sufficient from a least-privilege perspective.
Learnt from: thomasyopes
PR: metriport/metriport#3545
File: packages/lambdas/src/write-to-s3.ts:37-37
Timestamp: 2025-03-28T23:56:32.920Z
Learning: In the Metriport codebase, Lambdas that process messages from queues (like write-to-s3.ts) should directly use the local implementation (e.g., ProcessWriteToS3Local) rather than using the factory function. This is because the factory would queue the operation again in cloud environments, potentially creating an infinite loop. The pattern is: application code uses factory → factory queues in cloud → Lambda processes queue using local implementation.
Learnt from: keshavsaharia
PR: metriport/metriport#3887
File: packages/lambdas/src/surescripts-receive-flat-file-response.ts:11-35
Timestamp: 2025-05-22T16:36:54.189Z
Learning: The Surescripts Lambda handlers in packages/lambdas/src/ are stub implementations that will be replaced with more solid implementations later. These stubs don't require the same level of error handling and logging as production code.
packages/shared/src/interface/external/ehr/healthie/allergy.ts (9)
Learnt from: RamilGaripov
PR: metriport/metriport#3976
File: packages/api/src/routes/medical/patient.ts:541-543
Timestamp: 2025-06-18T21:05:22.256Z
Learning: In packages/api/src/routes/medical/patient.ts, inline schema definitions like cohortIdSchema are acceptable and don't need to be moved to separate schema files when the user prefers to keep them inline.
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.
Learnt from: thomasyopes
PR: metriport/metriport#3936
File: packages/core/src/external/ehr/athenahealth/index.ts:936-943
Timestamp: 2025-06-06T13:01:10.264Z
Learning: In the AthenaHealth allergy creation code, only the first reaction is processed intentionally - this is a design decision, not a bug. The code `const snomedCodings = snomedCodingsPairs[0];` deliberately takes only the first reaction from multiple possible reactions.
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: thomasyopes
PR: metriport/metriport#3970
File: packages/shared/src/interface/external/ehr/athenahealth/vaccine.ts:4-4
Timestamp: 2025-06-06T16:45:21.766Z
Learning: In Athenahealth EHR integration schemas, property names like "vaccineids" are intentionally preserved to match the external API response format since responses are returned directly without internal transformation or usage.
Learnt from: thomasyopes
PR: metriport/metriport#3981
File: packages/core/src/external/ehr/canvas/index.ts:0-0
Timestamp: 2025-06-10T20:13:16.532Z
Learning: Canvas EHR does not support the AllergyIntolerance clinicalStatus code "resolved"; only "active" and "inactive" are accepted.
Learnt from: keshavsaharia
PR: metriport/metriport#3885
File: packages/core/src/external/surescripts/schema/load.ts:65-71
Timestamp: 2025-05-30T03:42:53.380Z
Learning: In Surescripts schema files like `packages/core/src/external/surescripts/schema/load.ts`, the `key` property in field definitions is only used for direct one-to-one field mappings. When multiple fields are derived from the same source property but with different transformations (like extracting date vs. time portions), they should not have `key` properties as they represent transformations rather than direct mappings.
Learnt from: RamilGaripov
PR: metriport/metriport#3676
File: packages/core/src/command/hl7v2-subscriptions/hl7v2-to-fhir-conversion/shared.ts:1-10
Timestamp: 2025-04-16T00:25:25.196Z
Learning: The circular dependency between shared.ts (importing getPatientIdsOrFail) and adt/utils.ts (using unpackPidFieldOrFail) will be addressed in a follow-up PR.
Learnt from: lucasdellabella
PR: metriport/metriport#4098
File: packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts:10-22
Timestamp: 2025-06-27T01:50:14.227Z
Learning: In packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts, the patient fields patientData.firstName, patientData.lastName, and patientData.dob are guaranteed to be non-nullable values, so defensive null/undefined checks are not needed when accessing these fields.
packages/core/src/external/ehr/healthie/index.ts (25)
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.
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#3940
File: packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts:82-86
Timestamp: 2025-05-31T21:58:28.502Z
Learning: In packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts, the mutable array operations using push() on resourcesMutable and hydratedMutable (lines 82-86 and 100-103) have been explicitly accepted as exceptions to the immutability guidelines after previous discussion.
Learnt from: thomasyopes
PR: metriport/metriport#4000
File: packages/core/src/external/ehr/athenahealth/index.ts:504-507
Timestamp: 2025-06-11T21:39:26.805Z
Learning: In AthenaHealth write-back (`packages/core/src/external/ehr/athenahealth/index.ts`), only the condition statuses “relapse” and “recurrence” are currently mapped to AthenaHealth problem statuses (“CHRONIC”); other FHIR clinicalStatus values (e.g., “active”, “resolved”, “inactive”, “remission”) are not yet supported.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:0-0
Timestamp: 2025-05-28T19:20:47.442Z
Learning: In packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:27-49
Timestamp: 2025-05-28T19:22:09.281Z
Learning: In packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Learnt from: thomasyopes
PR: metriport/metriport#4090
File: packages/core/src/command/conversion-fhir/conversion-fhir-cloud.ts:30-30
Timestamp: 2025-06-25T01:55:42.627Z
Learning: In packages/core/src/command/conversion-fhir/conversion-fhir-cloud.ts, the FHIR converter Lambda endpoint is controlled by the team and guaranteed to return valid JSON in the expected Bundle<Resource> format, so JSON.parse() error handling and type validation are not necessary for this specific endpoint.
Learnt from: RamilGaripov
PR: metriport/metriport#3976
File: packages/api/src/routes/medical/patient.ts:541-543
Timestamp: 2025-06-18T21:05:22.256Z
Learning: In packages/api/src/routes/medical/patient.ts, inline schema definitions like cohortIdSchema are acceptable and don't need to be moved to separate schema files when the user prefers to keep them inline.
Learnt from: lucasdellabella
PR: metriport/metriport#3866
File: packages/api/src/routes/internal/medical/organization.ts:95-98
Timestamp: 2025-05-27T15:54:47.774Z
Learning: The conversion of the GET `/internal/organization` endpoint from returning a single organization to returning an array of organizations (batch retrieval) in `packages/api/src/routes/internal/medical/organization.ts` was an intentional breaking change planned by the team.
Learnt from: keshavsaharia
PR: metriport/metriport#4045
File: packages/core/src/external/surescripts/fhir/coverage.ts:0-0
Timestamp: 2025-06-18T18:34:10.489Z
Learning: Coverage resources in Surescripts FHIR conversion are currently excluded from bundles to prevent skewing data lift metrics. The team plans to examine available insurance data thoroughly before including properly structured Coverage resources with mandatory FHIR R4 elements like beneficiary and payor references.
Learnt from: leite08
PR: metriport/metriport#3944
File: packages/core/src/command/consolidated/search/fhir-resource/ingest-lexical.ts:53-53
Timestamp: 2025-06-01T02:28:19.913Z
Learning: In packages/core/src/command/consolidated/search/fhir-resource/ingest-lexical.ts, the processErrors function intentionally throws MetriportError to bubble errors up the call stack rather than handling them locally. This is by design - errors from ingestPatientConsolidated should propagate upward rather than being caught at immediate calling locations.
Learnt from: thomasyopes
PR: metriport/metriport#3788
File: packages/api/src/external/ehr/shared/utils/bundle.ts:83-93
Timestamp: 2025-05-08T19:41:36.533Z
Learning: In the Metriport codebase, the team prefers to let errors bubble up naturally in some cases rather than adding explicit error handling at every layer, as demonstrated in the refreshEhrBundle function in the bundle.ts file.
Learnt from: lucasdellabella
PR: metriport/metriport#4098
File: packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts:10-22
Timestamp: 2025-06-27T01:50:14.227Z
Learning: In packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts, the patient fields patientData.firstName, patientData.lastName, and patientData.dob are guaranteed to be non-nullable values, so defensive null/undefined checks are not needed when accessing these fields.
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/canvas/index.ts:451-469
Timestamp: 2025-04-21T17:07:30.574Z
Learning: The `getMetriportOnlyBundleByResourceType` method in CanvasApi returns `Promise<Bundle | undefined>` because the Metriport-only bundle is a computed artifact that may not exist yet. In contrast, `getBundleByResourceType` returns `Promise<Bundle>` because it can always fetch from the EHR API if the S3 cached bundle doesn't exist.
Learnt from: thomasyopes
PR: metriport/metriport#3771
File: packages/api/src/routes/internal/ehr/healthie/secret-key.ts:24-31
Timestamp: 2025-05-01T16:11:28.575Z
Learning: The function `getHealthieSecretKeyInfo` in the Healthie EHR integration throws appropriate MetriportErrors when required data is missing, so it will never return undefined or an empty object.
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/resource-diff/utils.ts:0-0
Timestamp: 2025-04-17T21:27:11.591Z
Learning: For the function `getSupportedResources` in resource-diff utils, returning an empty array for unsupported EHR sources is preferred over throwing an error, as it allows the code to gracefully handle unsupported sources without disruption.
Learnt from: thomasyopes
PR: metriport/metriport#4061
File: packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/run-job.ts:34-47
Timestamp: 2025-06-19T22:44:49.393Z
Learning: In packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/run-job.ts, the team prefers to keep refreshEhrBundles operations grouped using fire-and-forget pattern rather than awaiting all operations with Promise.allSettled(). This allows individual refresh operations to run independently without blocking the job runner.
Learnt from: thomasyopes
PR: metriport/metriport#3891
File: packages/api/src/routes/internal/ehr/patient.ts:142-142
Timestamp: 2025-06-20T15:35:00.546Z
Learning: In the EHR resource diff contribution system, there are no "invalid" resource types. The system is designed to gracefully handle any resource type string by attempting to find a corresponding bundle, and if no bundle exists for that resource type, it will simply exit early rather than throwing an error.
Learnt from: thomasyopes
PR: metriport/metriport#3960
File: packages/core/src/external/ehr/command/get-appointments/ehr-get-appointments-direct.ts:11-19
Timestamp: 2025-06-05T16:28:33.728Z
Learning: In the EhrGetAppointmentsDirect class in packages/core/src/external/ehr/command/get-appointments/ehr-get-appointments-direct.ts, type casting `as T[]` for the handler return value is considered safe and doesn't require additional runtime validation by the user thomasyopes.
Learnt from: leite08
PR: metriport/metriport#3953
File: packages/core/src/command/consolidated/search/fhir-resource/__tests__/search-consolidated-setup.ts:28-30
Timestamp: 2025-06-03T21:02:23.374Z
Learning: The `makePatient()` function returns `PatientWithId` type which requires the `id` field to be present, ensuring `patient.id` is never undefined.
Learnt from: leite08
PR: metriport/metriport#4034
File: packages/core/src/command/patient-import/patient-or-record-failed.ts:19-30
Timestamp: 2025-06-16T17:03:23.069Z
Learning: In patient import error handling functions like setPatientOrRecordFailed, the team prefers Promise.all over Promise.allSettled to ensure atomic all-or-nothing behavior - if either the job update or patient record update fails, the entire operation should fail rather than allowing partial success.
Learnt from: thomasyopes
PR: metriport/metriport#3754
File: packages/api/src/routes/ehr/healthie/appointment-webhook.ts:46-55
Timestamp: 2025-04-30T21:02:35.616Z
Learning: In the Healthie webhook endpoints, errors should be allowed to propagate (not caught and suppressed) so that webhook senders will retry the request. The Healthie client ensures appointments will have attendees, so specific error handling for missing attendees is not needed.
Learnt from: thomasyopes
PR: metriport/metriport#3771
File: packages/core/src/util/webhook.ts:34-45
Timestamp: 2025-05-01T16:10:45.273Z
Learning: The webhook signature verification code in packages/core/src/util/webhook.ts is copied directly from Healthie's documentation and should not be modified to maintain exact compliance with their implementation.
Learnt from: thomasyopes
PR: metriport/metriport#4090
File: packages/core/src/command/conversion-fhir/conversion-fhir-direct.ts:18-25
Timestamp: 2025-06-25T01:56:08.732Z
Learning: In packages/core/src/command/conversion-fhir/conversion-fhir-direct.ts, the ConversionFhirDirect class is designed for local testing purposes and does not require comprehensive error handling for HTTP requests, as confirmed by the user thomasyopes.
Learnt from: keshavsaharia
PR: metriport/metriport#4075
File: packages/core/src/external/surescripts/fhir/medication-request.ts:76-83
Timestamp: 2025-06-25T18:42:07.231Z
Learning: In packages/core/src/external/surescripts/fhir/medication-request.ts, the getDispenseNote and getDosageInstruction functions are intentionally identical because the dashboard requires both the note and dosageInstruction fields of MedicationRequest to be populated with detail.directions for proper note display functionality.
🧬 Code Graph Analysis (2)
packages/core/src/external/ehr/bundle/bundle-shared.ts (1)
packages/core/src/external/ehr/healthie/index.ts (1)
  • supportedHealthieResources (73-79)
packages/core/src/external/ehr/healthie/index.ts (10)
packages/fhir-sdk/src/index.ts (4)
  • MedicationStatement (51-51)
  • AllergyIntolerance (36-36)
  • Observation (52-52)
  • Bundle (37-37)
packages/shared/src/interface/external/ehr/healthie/medication.ts (2)
  • medicationsGraphqlSchema (17-21)
  • Medication (15-15)
packages/shared/src/interface/external/ehr/healthie/immunization.ts (2)
  • immunizationsGraphqlSchema (12-18)
  • Immunization (10-10)
packages/shared/src/interface/external/ehr/healthie/allergy.ts (2)
  • allergiesGraphqlSchema (17-23)
  • Allergy (15-15)
packages/shared/src/interface/external/ehr/healthie/condition.ts (2)
  • conditionsGraphqlSchema (12-18)
  • Condition (10-10)
packages/shared/src/interface/external/ehr/healthie/lab.ts (2)
  • labOrdersGraphqlSchema (34-38)
  • LabOrder (32-32)
packages/shared/src/index.ts (2)
  • BadRequestError (40-40)
  • toTitleCase (15-15)
packages/shared/src/interface/external/ehr/fhir-resource.ts (2)
  • EhrStrictFhirResource (37-37)
  • ehrStrictFhirResourceSchema (30-36)
packages/core/src/external/ehr/shared.ts (1)
  • fetchEhrBundleUsingCache (660-680)
packages/shared/src/common/date.ts (1)
  • buildDayjs (93-95)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: check-pr / lint-build-test
  • GitHub Check: check-pr / lint-build-test
  • GitHub Check: check-pr / lint-build-test
  • GitHub Check: check-pr / lint-build-test
  • GitHub Check: Analyze (javascript)
  • GitHub Check: ihe_stack / deploy
  • GitHub Check: secrets_cdk_stack / deploy
  • GitHub Check: infra-api-lambdas / deploy
  • GitHub Check: api / deploy
  • GitHub Check: mllp-server / deploy
🔇 Additional comments (21)
packages/core/src/external/ehr/bundle/bundle-shared.ts (2)

7-7: LGTM - Import follows established pattern

The import statement for supportedHealthieResources is correctly placed and follows the same pattern as other EHR source imports.


107-107: LGTM - Conditional logic is consistent

The new conditional branch for Healthie follows the exact same pattern as the existing EHR sources, maintaining consistency with the established architecture.

packages/core/src/external/ehr/command/get-bundle-by-resource-type.ts (2)

7-7: LGTM - Import follows established naming pattern

The import statement correctly uses the alias pattern (getBundleByResourceType as getBundleByResourceTypeHealthie) that matches the existing imports for other EHR sources.


38-38: LGTM - Handler mapping is correctly implemented

The mapping of EhrSources.healthie to getBundleByResourceTypeHealthie follows the established pattern and replaces the previous undefined value with the actual handler function.

packages/core/src/external/ehr/job/create-resource-diff-bundles/shared.ts (1)

19-19: LGTM - Addition follows established pattern

The addition of EhrSources.healthie to the array is consistent with the existing pattern and automatically updates the derived type EhrSourceWithCreateResourceDiffBundles.

packages/api/src/external/ehr/shared/command/bundle/contribute-resource-diff-bundle.ts (2)

8-8: LGTM - Import is correctly added

The import statement for EhrSources is properly placed and follows the established import pattern.


51-51: LGTM - Early return follows established pattern

The early return for Healthie is correctly placed after bundle validation and follows the same pattern as the existing Athena custom fields check.

packages/core/src/external/ehr/healthie/command/get-bundle-by-resource-type.ts (2)

5-16: LGTM - Function signature and parameter handling

The function signature matches the expected interface and the parameter destructuring follows the established pattern used in other EHR implementations.


17-29: LGTM - Client creation and method invocation

The client creation using createHealthieClient and the subsequent method call follow the established pattern. The parameter mapping, particularly ehrPatientId to healthiePatientId, is correctly implemented.

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

7-11: Barrel exports look good

The new Healthie resource barrels are correctly re-exported and alphabetically consistent with existing ones.

packages/shared/src/interface/external/ehr/healthie/condition.ts (2)

3-9: Schema is clear and defensive

All external fields are nullable where appropriate, preventing runtime validation failures on sparse payloads. No issues spotted.


12-19: GraphQL wrapper mirrors Healthie response

The nested shape (data.user.diagnoses) matches the pattern used in other Healthie modules, keeping things consistent.

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

12-19: GraphQL schema consistent

Matches the other resource wrappers; no concerns.

packages/shared/src/interface/external/ehr/healthie/medication.ts (2)

3-14: Comprehensive medication schema

The field set aligns with Healthie docs and nullable handling is appropriate. LGTM.


17-22: Wrapper shape aligns with existing conventions

The data.medications path is straightforward and consistent across modules.

packages/shared/src/interface/external/ehr/healthie/lab.ts (3)

3-10: Nested result/request schemas are well-structured

Enumerated interpretation values guard against invalid strings; nullable properties account for partial lab data. Looks good.


26-33: Top-level LabOrder covers key attributes

No correctness issues detected.


34-39: GraphQL envelope matches other resources

Consistent pattern; safe to merge.

packages/core/src/external/ehr/healthie/index.ts (1)

73-86: Supported-resource helpers look good.
Implementation cleanly restricts resource types via type-guard – no concerns here.

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

3-14: Schema LGTM.
The Zod schema captures current API enum space and permits nullables where expected.

packages/infra/lib/ehr-nested-stack.ts (1)

612-669: Bucket wiring looks safe.
Optional chaining guards (?.grantWrite) prevent failures when ehrResponsesBucket is undefined; env-var injection is likewise conditional. No action needed.

Comment on lines +1031 to +1076
private convertLabOrdersToFhir(patientId: string, labOrder: LabOrder): Observation[] | undefined {
const testDate = labOrder.test_date;
if (!labOrder.status || !testDate || labOrder.lab_results.length < 1) return undefined;
const isFinal = labOrder.status === "completed";
if (!isFinal) return undefined;
return labOrder.lab_results.flatMap(labResult => {
if (!labResult.lab_observation_requests || labResult.lab_observation_requests.length < 1) {
return [];
}
return labResult.lab_observation_requests.flatMap(labObservationRequest => {
const labAnalyte = labObservationRequest.lab_analyte;
if (!labAnalyte) return [];
return labObservationRequest.lab_observation_results.flatMap(labObservationResult => {
if (
!labObservationResult.quantitative_result ||
!labObservationResult.units ||
!labObservationResult.reference_range
) {
return [];
}
const quantitativeResult = labObservationResult.quantitative_result;
const units = labObservationResult.units;
return {
resourceType: "Observation",
id: labObservationResult.id,
subject: { reference: `Patient/${patientId}` },
status: "final",
code: { text: labAnalyte },
category: [
{
coding: [
{
system: "http://terminology.hl7.org/CodeSystem/observation-category",
code: "laboratory",
display: "Laboratory",
},
],
},
],
effectiveDateTime: buildDayjs(testDate).toISOString(),
valueQuantity: { value: parseFloat(quantitativeResult), unit: units },
referenceRange: [{ text: labObservationResult.reference_range }],
interpretation: [{ text: toTitleCase(labObservationResult.interpretation) }],
...(labObservationResult.notes ? { note: [{ text: labObservationResult.notes }] } : {}),
};
});
Copy link

@coderabbitai coderabbitai bot Jul 9, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

Null-safety for interpretation to prevent runtime crash.

toTitleCase(labObservationResult.interpretation) will throw when interpretation is null/undefined (field is nullable in schema). Add a guard before building the interpretation field.

-            interpretation: [{ text: toTitleCase(labObservationResult.interpretation) }],
+            ...(labObservationResult.interpretation
+              ? { interpretation: [{ text: toTitleCase(labObservationResult.interpretation) }] }
+              : {}),
🤖 Prompt for AI Agents
In packages/core/src/external/ehr/healthie/index.ts between lines 1031 and 1076,
the code calls toTitleCase on labObservationResult.interpretation without
checking if interpretation is null or undefined, which can cause a runtime
crash. Add a guard to verify interpretation is not null or undefined before
calling toTitleCase and only include the interpretation field in the returned
object if this check passes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's required via zod

Copy link

Choose a reason for hiding this comment

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

🧩 Analysis chain

@thomasyopes You're absolutely right! Looking at the Zod schema definition in packages/shared/src/interface/external/ehr/healthie/lab.ts, the interpretation field is defined as z.enum(["high", "low", "normal"]) which makes it a required, non-nullable field. The Zod validation ensures that interpretation will always have one of these three values, so the null-safety check is unnecessary.

The CodeRabbit suggestion was based on the assumption that the field could be null/undefined, but since it's validated as a required enum by Zod, toTitleCase(labObservationResult.interpretation) is safe to call without additional guards.


🏁 Script executed:

#!/bin/bash
# Find the Zod schema definition for lab observation result
fd -e ts -e js | xargs grep -l "interpretation.*enum\|interpretation.*string" | head -5

Length of output: 515


🏁 Script executed:

#!/bin/bash
# Look for the lab observation result schema definition
rg "labOrderObservationResultSchema" -A 20 -B 5

Length of output: 3409


🏁 Script executed:

#!/bin/bash
# Search for interpretation field in the lab-related schema files
rg "interpretation" packages/shared/src/interface/external/ehr/healthie/lab.ts -A 3 -B 3

Length of output: 358


@thomasyopes You're absolutely right! Looking at the Zod schema definition in packages/shared/src/interface/external/ehr/healthie/lab.ts, the interpretation field is defined as z.enum(["NORMAL", "ABNORMAL", "CRITICAL", "UNKNOWN"]) which makes it a required, non-nullable field. The Zod validation ensures that interpretation will always have one of these four enum values, so the null-safety check is unnecessary.

The CodeRabbit suggestion was based on the assumption that the field could be null/undefined, but since it's validated as a required enum by Zod, toTitleCase(labObservationResult.interpretation) is safe to call without additional guards.


🧬 Code Graph Analysis Results

Relevant snippets from packages/shared/src/interface/external/ehr/healthie/patient.ts (lines 22-51)

export type Patient = z.infer<typeof patientSchema>;

export type PatientGraphql = z.infer<typeof patientGraphqlSchema>;

export const patientGraphqlSchema = z.object({
  data: z.object({
    user: patientSchema.nullable(),
  }),
});

export type PatientQuickNotesGraphql = z.infer<typeof patientQuickNotesGraphqlSchema>;

export const patientQuickNotesGraphqlSchema = z.object({
  data: z.object({
    user: patientQuickNotesSchema.nullable(),
  }),
});

export type PatientUpdateQuickNotesGraphql = z.infer<typeof patientUpdateQuickNotesGraphqlSchema>;

export const patientUpdateQuickNotesGraphqlSchema = z.object({
  data: z.object({
    updateClient: z.object({
      user: patientQuickNotesSchema.nullable(),
    }),
  }),
});
  • These define Zod schemas and inferred types for GraphQL responses related to Patient, PatientQuickNotes, and PatientUpdateQuickNotes.
  • The schemas are used in makeRequest calls in HealthieApi to validate and parse GraphQL responses, ensuring type safety and data correctness.

Relevant snippets from packages/shared/src/interface/external/ehr/healthie/medication.ts (lines 15-22)

export type Medication = z.infer<typeof medicationSchema>;

export const medicationsGraphqlSchema = z.object({
  data: z.object({
    medications: medicationSchema.array(),
  }),
});

export type MedicationsGraphql = z.infer<typeof medicationsGraphqlSchema>;
  • Defines Zod schemas and types for Medication and the GraphQL response containing medications.
  • Used in HealthieApi.getMedicationStatements to validate the GraphQL response.

Relevant snippets from packages/shared/src/interface/external/ehr/healthie/allergy.ts (lines 15-24)

export type Allergy = z.infer<typeof allergySchema>;

export const allergiesGraphqlSchema = z.object({
  data: z.object({
    user: z.object({
      allergy_sensitivities: allergySchema.array(),
    }),
  }),
});

export type AllergiesGraphql = z.infer<typeof allergiesGraphqlSchema>;
  • Defines Zod schemas and types for Allergy and the GraphQL response containing allergy sensitivities.
  • Used in HealthieApi.getAllergies to validate the GraphQL response.

Relevant snippets from packages/shared/src/interface/external/ehr/healthie/condition.ts (lines 10-19)

export type Condition = z.infer<typeof conditionSchema>;

export const conditionsGraphqlSchema = z.object({
  data: z.object({
    user: z.object({
      diagnoses: conditionSchema.array(),
    }),
  }),
});

export type ConditionsGraphql = z.infer<typeof conditionsGraphqlSchema>;
  • Defines Zod schemas and types for Condition and the GraphQL response containing diagnoses.
  • Used in HealthieApi.getConditions to validate the GraphQL response.

Relevant snippets from packages/shared/src/interface/external/ehr/healthie/immunization.ts (lines 10-19)

export type Immunization = z.infer<typeof immunizationSchema>;

export const immunizationsGraphqlSchema = z.object({
  data: z.object({
    user: z.object({
      immunizations: immunizationSchema.array(),
    }),
  }),
});

export type ImmunizationsGraphql = z.infer<typeof immunizationsGraphqlSchema>;
  • Defines Zod schemas and types for Immunization and the GraphQL response containing immunizations.
  • Used in HealthieApi.getImmunizations to validate the GraphQL response.

Relevant snippets from packages/shared/src/interface/external/ehr/healthie/lab.ts (lines 32-39)

export type LabOrder = z.infer<typeof labOrderSchema>;

export const labOrdersGraphqlSchema = z.object({
  data: z.object({
    labOrders: labOrderSchema.array(),
  }),
});

export type LabOrdersGraphql = z.infer<typeof labOrdersGraphqlSchema>;
  • Defines Zod schemas and types for LabOrder and the GraphQL response containing lab orders.
  • Used in HealthieApi.getLabObservations to validate the GraphQL response.

Relevant snippets from packages/shared/src/interface/external/ehr/fhir-resource.ts (lines 30-37)

export const ehrStrictFhirResourceSchema = z.intersection(
  z.object({
    id: z.string(),
    resourceType: z.string(),
  }),
  ehrFhirResourceSharedFieldsSchema
);

export type EhrStrictFhirResource = z.infer<typeof ehrStrictFhirResourceSchema>;
  • Defines a Zod schema and type for strict FHIR resources with required id and resourceType fields.
  • Used in HealthieApi.getBundleByResourceType to parse and validate converted FHIR resources before bundling.

Relevant snippets from packages/core/src/external/ehr/shared.ts (lines 122-267)

export async function makeRequest<T>({
  ehr,
  cxId,
  practiceId,
  patientId,
  s3Path,
  axiosInstance,
  url,
  method,
  data,
  headers,
  schema,
  additionalInfo,
  debug,
  emptyResponse = false,
}: MakeRequestParams<T>): Promise<T> {
  // Makes an HTTP request using axiosInstance, handles retries, error handling,
  // logs requests and responses, uploads responses/errors to S3 if configured,
  // and validates the response body against the provided Zod schema.
  // Throws appropriate errors (BadRequestError, NotFoundError, MetriportError) on failure.
}
  • This shared makeRequest function is used by HealthieApi internally to perform GraphQL requests with validation via Zod schemas.
  • It ensures that responses conform to the expected schema, throwing errors if validation fails.

Summary of relevance:

  • The user comment "It's required via zod" relates to the use of Zod schemas for validating GraphQL responses and FHIR resource conversions in HealthieApi.
  • The above snippets show the Zod schemas imported and used in the file for type-safe parsing of external data.
  • The shared makeRequest function implements the actual request and validation logic using these schemas.
  • The ehrStrictFhirResourceSchema is used to validate converted FHIR resources before bundling.

These snippets provide the context needed to understand how Zod is integrated and required in the packages/core/src/external/ehr/healthie/index.ts file.


✏️ Learnings added
Learnt from: thomasyopes
PR: metriport/metriport#4164
File: packages/core/src/external/ehr/healthie/index.ts:1031-1076
Timestamp: 2025-07-09T17:18:28.895Z
Learning: In packages/core/src/external/ehr/healthie/index.ts, the `interpretation` field in `labObservationResult` is defined as a required enum in the Zod schema (`z.enum(["high", "low", "normal"])`), making null-safety checks unnecessary when calling `toTitleCase(labObservationResult.interpretation)`.

Learnt from: thomasyopes
PR: metriport/metriport#4164
File: packages/core/src/external/ehr/healthie/index.ts:1031-1076
Timestamp: 2025-07-09T17:18:28.895Z
Learning: In packages/core/src/external/ehr/healthie/index.ts, the `interpretation` field in `labObservationResult` is defined as a required enum in the Zod schema (`z.enum(["NORMAL", "ABNORMAL", "CRITICAL", "UNKNOWN"])`), making null-safety checks unnecessary when calling `toTitleCase(labObservationResult.interpretation)`.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.

Learnt from: thomasyopes
PR: metriport/metriport#4090
File: packages/core/src/command/conversion-fhir/conversion-fhir-cloud.ts:30-30
Timestamp: 2025-06-25T01:55:42.627Z
Learning: In packages/core/src/command/conversion-fhir/conversion-fhir-cloud.ts, the FHIR converter Lambda endpoint is controlled by the team and guaranteed to return valid JSON in the expected Bundle<Resource> format, so JSON.parse() error handling and type validation are not necessary for this specific endpoint.

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: lucasdellabella
PR: metriport/metriport#4098
File: packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts:10-22
Timestamp: 2025-06-27T01:50:14.227Z
Learning: In packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts, the patient fields patientData.firstName, patientData.lastName, and patientData.dob are guaranteed to be non-nullable values, so defensive null/undefined checks are not needed when accessing these fields.

Learnt from: keshavsaharia
PR: metriport/metriport#4075
File: packages/core/src/external/surescripts/fhir/medication-request.ts:76-83
Timestamp: 2025-06-25T18:42:07.231Z
Learning: In packages/core/src/external/surescripts/fhir/medication-request.ts, the getDispenseNote and getDosageInstruction functions are intentionally identical because the dashboard requires both the note and dosageInstruction fields of MedicationRequest to be populated with detail.directions for proper note display functionality.

Learnt from: thomasyopes
PR: metriport/metriport#4090
File: packages/core/src/command/conversion-fhir/conversion-fhir-direct.ts:18-25
Timestamp: 2025-06-25T01:56:08.732Z
Learning: In packages/core/src/command/conversion-fhir/conversion-fhir-direct.ts, the ConversionFhirDirect class is designed for local testing purposes and does not require comprehensive error handling for HTTP requests, as confirmed by the user thomasyopes.

Learnt from: thomasyopes
PR: metriport/metriport#4000
File: packages/core/src/external/ehr/athenahealth/index.ts:504-507
Timestamp: 2025-06-11T21:39:26.805Z
Learning: In AthenaHealth write-back (`packages/core/src/external/ehr/athenahealth/index.ts`), only the condition statuses “relapse” and “recurrence” are currently mapped to AthenaHealth problem statuses (“CHRONIC”); other FHIR clinicalStatus values (e.g., “active”, “resolved”, “inactive”, “remission”) are not yet supported.

Learnt from: RamilGaripov
PR: metriport/metriport#3976
File: packages/api/src/routes/medical/patient.ts:541-543
Timestamp: 2025-06-18T21:05:22.256Z
Learning: In packages/api/src/routes/medical/patient.ts, inline schema definitions like cohortIdSchema are acceptable and don't need to be moved to separate schema files when the user prefers to keep them inline.

Learnt from: leite08
PR: metriport/metriport#3940
File: packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts:82-86
Timestamp: 2025-05-31T21:58:28.502Z
Learning: In packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts, the mutable array operations using push() on resourcesMutable and hydratedMutable (lines 82-86 and 100-103) have been explicitly accepted as exceptions to the immutability guidelines after previous discussion.

Learnt from: leite08
PR: metriport/metriport#3953
File: packages/core/src/command/consolidated/search/fhir-resource/__tests__/search-consolidated-setup.ts:28-30
Timestamp: 2025-06-03T21:02:23.374Z
Learning: The `makePatient()` function returns `PatientWithId` type which requires the `id` field to be present, ensuring `patient.id` is never undefined.

Learnt from: CR
PR: metriport/metriport#0
File: .cursorrules:0-0
Timestamp: 2025-06-30T14:40:49.769Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : 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

Learnt from: leite08
PR: metriport/metriport#3942
File: packages/core/src/external/fhir/__tests__/location.ts:6-9
Timestamp: 2025-06-01T13:48:26.600Z
Learning: In TypeScript test code, don't flag deconstructed object parameters as needing simplification or refactoring. Test helper functions with nested optional object parameters (like `param?: { patient?: PatientWithId; location?: Partial<Location>; }`) are acceptable and should not be suggested for flattening.

Learnt from: thomasyopes
PR: metriport/metriport#3960
File: packages/core/src/external/ehr/command/get-appointments/ehr-get-appointments-direct.ts:11-19
Timestamp: 2025-06-05T16:28:33.728Z
Learning: In the EhrGetAppointmentsDirect class in packages/core/src/external/ehr/command/get-appointments/ehr-get-appointments-direct.ts, type casting `as T[]` for the handler return value is considered safe and doesn't require additional runtime validation by the user thomasyopes.

Learnt from: keshavsaharia
PR: metriport/metriport#4045
File: packages/shared/src/interface/external/surescripts/plan-code.ts:1-3
Timestamp: 2025-06-18T17:22:24.597Z
Learning: In packages/shared/src/interface/external/surescripts/plan-code.ts, the getPlanCodeName function should return undefined for invalid plan codes rather than throwing errors, as per user preference for graceful error handling.

Learnt from: lucasdellabella
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/resource-diff/steps/start/ehr-start-resource-diff-local.ts:0-0
Timestamp: 2025-04-21T03:47:54.332Z
Learning: In the EHR resource diff implementation, bundles should always have an `entry` property, and code should be allowed to throw if `entry` is missing rather than using null-coalescing operators, as this represents an unexpected state that should be caught and addressed.

Learnt from: thomasyopes
PR: metriport/metriport#3466
File: packages/api/src/routes/ehr/elation/chart.ts:20-37
Timestamp: 2025-03-17T15:30:34.647Z
Learning: The request body parsing in packages/api/src/routes/ehr/elation/chart.ts is tracked with TODO referencing issue #2170 and will be handled in a separate PR, not in PR #3466.

Learnt from: leite08
PR: metriport/metriport#3463
File: packages/api/src/routes/internal/medical/patient-settings.ts:31-49
Timestamp: 2025-03-19T01:11:01.406Z
Learning: In the Metriport codebase, Zod schema validation errors in routes are intentionally allowed to propagate to the central error handler (packages/api/src/routes/helpers/default-error-handler.ts) rather than being caught with try/catch blocks in individual route handlers. The error handler automatically processes ZodErrors and returns a 400 Bad Request response with formatted validation details.

Learnt from: RamilGaripov
PR: metriport/metriport#3675
File: packages/api/src/routes/internal/hl7/index.ts:0-0
Timestamp: 2025-04-23T06:31:50.128Z
Learning: RamilGaripov prefers using Zod schema validation for parsing and validating all query parameters in routes as it's a cleaner way to write route logic, rather than using separate validation methods like getUUIDFrom().orFail() followed by schema validation.

Learnt from: keshavsaharia
PR: metriport/metriport#4045
File: packages/core/src/external/surescripts/fhir/coverage.ts:0-0
Timestamp: 2025-06-18T18:34:10.489Z
Learning: Coverage resources in Surescripts FHIR conversion are currently excluded from bundles to prevent skewing data lift metrics. The team plans to examine available insurance data thoroughly before including properly structured Coverage resources with mandatory FHIR R4 elements like beneficiary and payor references.

Learnt from: lucasdellabella
PR: metriport/metriport#3866
File: packages/api/src/routes/internal/medical/organization.ts:95-98
Timestamp: 2025-05-27T15:54:47.774Z
Learning: The conversion of the GET `/internal/organization` endpoint from returning a single organization to returning an array of organizations (batch retrieval) in `packages/api/src/routes/internal/medical/organization.ts` was an intentional breaking change planned by the team.

Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:0-0
Timestamp: 2025-05-28T19:20:47.442Z
Learning: In packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.

Learnt from: keshavsaharia
PR: metriport/metriport#4045
File: packages/core/src/external/surescripts/fhir/shared.ts:87-93
Timestamp: 2025-06-18T18:50:40.968Z
Learning: The `getResourceFromResourceMap` function in `packages/core/src/external/surescripts/fhir/shared.ts` works correctly as implemented. The comparison `resourceValue === resourceMap[key]` where `resourceValue = resource[key]` is intentional and functions as designed, despite appearing to compare different types.

Learnt from: leite08
PR: metriport/metriport#0
File: :0-0
Timestamp: 2025-03-05T18:43:30.389Z
Learning: For backmerge PRs at metriport/metriport, only verify two things: (1) that the source branch is `master` and destination branch is `develop`, and (2) that there's a link to at least one PR (usually a "patch" PR) in the description. No need for detailed review comments or updates to the PR description unless there's an issue with these criteria.

Learnt from: leite08
PR: metriport/metriport#3611
File: packages/utils/src/fhir-converter/s3-to-lambda.ts:29-47
Timestamp: 2025-04-05T16:02:02.517Z
Learning: For release PRs (where head branch is `develop` and base branch is `master`), don't suggest code changes as these have already been reviewed in previous PRs. Instead, focus only on checking if the PR description follows the template and practices, and if the PR is pointing to the correct base branch (`master`).

Learnt from: lucasdellabella
PR: metriport/metriport#3907
File: packages/terminology/src/seed/seed-ndc-from-fda.ts:91-113
Timestamp: 2025-05-28T05:28:26.896Z
Learning: On PRs with "release" in the title, only provide very high priority feedback and avoid lower priority suggestions like refactoring or optimization improvements.

Learnt from: leite08
PR: metriport/metriport#3749
File: packages/core/src/command/patient-import/record/create-headers-file.ts:16-27
Timestamp: 2025-04-28T22:57:36.763Z
Learning: Focus improvement suggestions on feature branches rather than release PRs. Release PRs should be treated with higher caution as they're focused on getting tested code into production.

Learnt from: lucasdellabella
PR: metriport/metriport#0
File: :0-0
Timestamp: 2025-03-14T13:44:44.651Z
Learning: Avoid adding AI-generated summaries to PRs with "RELEASE" in the title.

Comment on lines +939 to +953
private convertImmunizationToFhir(
patientId: string,
immunization: Immunization
): ImmunizationFhir {
const isCompleted = immunization.status === "completed";
return {
resourceType: "Immunization",
id: immunization.id,
patient: { reference: `Patient/${patientId}` },
status: isCompleted ? "completed" : "not-done",
vaccineCode: { coding: [{ system: CVX_URL, code: immunization.cvx_code }] },
occurrenceDateTime: buildDayjs(immunization.received_at).toISOString(),
...(immunization.additional_notes ? { note: [{ text: immunization.additional_notes }] } : {}),
};
}
Copy link

@coderabbitai coderabbitai bot Jul 9, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

Guard against null cvx_code before building vaccineCode.

immunization.cvx_code is nullable, but the current implementation always injects it, producing { code: null } – an invalid FHIR element that will trip strict validators downstream.

-      vaccineCode: { coding: [{ system: CVX_URL, code: immunization.cvx_code }] },
+      ...(immunization.cvx_code
+        ? { vaccineCode: { coding: [{ system: CVX_URL, code: immunization.cvx_code }] } }
+        : { vaccineCode: { text: immunization.vaccine_name ?? "Immunization" } }),
🤖 Prompt for AI Agents
In packages/core/src/external/ehr/healthie/index.ts around lines 939 to 953, the
code always includes immunization.cvx_code in vaccineCode even when it is null,
resulting in an invalid FHIR element. Update the method to check if
immunization.cvx_code is non-null before adding the vaccineCode property; if it
is null, omit vaccineCode entirely to ensure valid FHIR output.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's required via zod

Copy link

Choose a reason for hiding this comment

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

🧩 Analysis chain

Let me check the immunization schema to confirm whether cvx_code is indeed required and non-nullable:

@thomasyopes You're absolutely right! I can see from the immunization schema that cvx_code is defined as z.coerce.string(), which means it's required and will be coerced to a string. Since the zod schema validation ensures cvx_code is always present and non-null when it reaches the conversion function, the null-checking suggestion in the AI comment is unnecessary.

The current implementation is correct as-is since the schema guarantees cvx_code will be a valid string value.


🏁 Script executed:

#!/bin/bash
# Check the immunization schema definition to see if cvx_code is required
cat packages/shared/src/interface/external/ehr/healthie/immunization.ts

Length of output: 592


@thomasyopes You're absolutely right! Looking at the immunization schema, I can confirm that cvx_code is defined as z.coerce.string(), which means it's required and will be coerced to a string. Since the zod schema validation ensures cvx_code is always present and non-null when it reaches the convertImmunizationToFhir method, the null-checking suggestion in the AI comment is indeed unnecessary.

The current implementation is correct as-is since the schema guarantees cvx_code will be a valid string value.


🧬 Code Graph Analysis Results

Relevant snippets from packages/shared/src/interface/external/ehr/healthie/patient.ts (lines 22-51)

export type Patient = z.infer<typeof patientSchema>;

export type PatientGraphql = z.infer<typeof patientGraphqlSchema>;

export const patientGraphqlSchema = z.object({
  data: z.object({
    user: patientSchema.nullable(),
  }),
});

export type PatientQuickNotesGraphql = z.infer<typeof patientQuickNotesGraphqlSchema>;

export const patientQuickNotesGraphqlSchema = z.object({
  data: z.object({
    user: patientQuickNotesSchema.nullable(),
  }),
});

export type PatientUpdateQuickNotesGraphql = z.infer<typeof patientUpdateQuickNotesGraphqlSchema>;

export const patientUpdateQuickNotesGraphqlSchema = z.object({
  data: z.object({
    updateClient: z.object({
      user: patientQuickNotesSchema.nullable(),
    }),
  }),
});
  • These define Zod schemas and inferred types for GraphQL responses related to Patient, PatientQuickNotes, and PatientUpdateQuickNotes.
  • The schemas are used for runtime validation of API responses in the HealthieApi class methods like getPatient, getPatientQuickNotes, and updatePatientQuickNotesWithLink.

Relevant snippets from packages/shared/src/interface/external/ehr/healthie/medication.ts (lines 15-22)

export type Medication = z.infer<typeof medicationSchema>;

export const medicationsGraphqlSchema = z.object({
  data: z.object({
    medications: medicationSchema.array(),
  }),
});

export type MedicationsGraphql = z.infer<typeof medicationsGraphqlSchema>;
  • These define the Zod schema and inferred types for Medication and the GraphQL response containing medications.
  • Used in getMedicationStatements method for validating the response.

Relevant snippets from packages/shared/src/interface/external/ehr/healthie/immunization.ts (lines 10-19)

export type Immunization = z.infer<typeof immunizationSchema>;

export const immunizationsGraphqlSchema = z.object({
  data: z.object({
    user: z.object({
      immunizations: immunizationSchema.array(),
    }),
  }),
});

export type ImmunizationsGraphql = z.infer<typeof immunizationsGraphqlSchema>;
  • Zod schemas and types for Immunization and its GraphQL response.
  • Used in getImmunizations method.

Relevant snippets from packages/shared/src/interface/external/ehr/healthie/allergy.ts (lines 15-24)

export type Allergy = z.infer<typeof allergySchema>;

export const allergiesGraphqlSchema = z.object({
  data: z.object({
    user: z.object({
      allergy_sensitivities: allergySchema.array(),
    }),
  }),
});

export type AllergiesGraphql = z.infer<typeof allergiesGraphqlSchema>;
  • Zod schemas and types for Allergy and its GraphQL response.
  • Used in getAllergies method.

Relevant snippets from packages/shared/src/interface/external/ehr/healthie/condition.ts (lines 10-19)

export type Condition = z.infer<typeof conditionSchema>;

export const conditionsGraphqlSchema = z.object({
  data: z.object({
    user: z.object({
      diagnoses: conditionSchema.array(),
    }),
  }),
});

export type ConditionsGraphql = z.infer<typeof conditionsGraphqlSchema>;
  • Zod schemas and types for Condition and its GraphQL response.
  • Used in getConditions method.

Relevant snippets from packages/shared/src/interface/external/ehr/healthie/lab.ts (lines 32-39)

export type LabOrder = z.infer<typeof labOrderSchema>;

export const labOrdersGraphqlSchema = z.object({
  data: z.object({
    labOrders: labOrderSchema.array(),
  }),
});

export type LabOrdersGraphql = z.infer<typeof labOrdersGraphqlSchema>;
  • Zod schemas and types for LabOrder and its GraphQL response.
  • Used in getLabObservations method.

Relevant snippets from packages/shared/src/interface/external/ehr/fhir-resource.ts (lines 30-37)

export const ehrStrictFhirResourceSchema = z.intersection(
  z.object({
    id: z.string(),
    resourceType: z.string(),
  }),
  ehrFhirResourceSharedFieldsSchema
);

export type EhrStrictFhirResource = z.infer<typeof ehrStrictFhirResourceSchema>;
  • Defines a strict Zod schema for FHIR resources with required id and resourceType.
  • Used in getBundleByResourceType method to parse and validate converted FHIR resources before bundling.

Relevant snippets from packages/core/src/external/ehr/shared.ts (lines 122-267)

export async function makeRequest<T>({
  ehr,
  cxId,
  practiceId,
  patientId,
  s3Path,
  axiosInstance,
  url,
  method,
  data,
  headers,
  schema,
  additionalInfo,
  debug,
  emptyResponse = false,
}: MakeRequestParams<T>): Promise<T> {
  // Makes HTTP request using axiosInstance with retries and error handling.
  // Validates response data against provided Zod schema.
  // On error, throws appropriate custom errors (BadRequestError, NotFoundError, MetriportError).
  // Saves request and response data to S3 for auditing if configured.
  // Parameters:
  // - ehr: EHR source identifier
  // - cxId, practiceId, patientId: context identifiers
  // - s3Path: path for saving responses
  // - axiosInstance: axios instance to use
  // - url, method, data, headers: HTTP request details
  // - schema: Zod schema to validate response
  // - additionalInfo: extra context for logging/errors
  // - debug: debug logging function
  // - emptyResponse: allow empty response and validate accordingly
  // Returns: parsed and validated response data of type T
  // Throws: MetriportError or subclasses on failure
}
  • This function is used internally by HealthieApi in its private makeRequest method to perform GraphQL requests and validate responses using Zod schemas.

Relevant snippets from packages/shared/src/index.ts (lines 40-42)

import {
  BadRequestError,
  MetriportError,
  NotFoundError,
  sleep,
  toTitleCase,
} from "@metriport/shared";
  • These error classes and utility functions are used throughout the HealthieApi class for error handling and minor data formatting.

Relevant snippet from packages/shared/src/common/date.ts (lines 93-95)

export function buildDayjs(date?: ConfigType, format?: string, strict?: boolean): dayjs.Dayjs {
  return dayjs.utc(date, format, strict);
}
  • Utility function used in HealthieApi to parse and format dates consistently.

Summary

The HealthieApi class in packages/core/src/external/ehr/healthie/index.ts relies heavily on Zod schemas imported from @metriport/shared/interface/external/ehr/healthie/* to validate GraphQL responses for various resource types such as Patient, Medication, Immunization, Allergy, Condition, and LabOrder. The makeRequest method uses a shared makeRequest function that performs HTTP requests and validates responses against these Zod schemas, throwing typed errors on failure.

The user comment "It's required via zod" likely refers to the fact that the data validation and typing in this file are enforced by Zod schemas imported from the shared interface packages, ensuring runtime validation of external EHR data.

These snippets provide the relevant context about the Zod schemas and their usage in the file.


✏️ Learnings added
Learnt from: thomasyopes
PR: metriport/metriport#4164
File: packages/core/src/external/ehr/healthie/index.ts:939-953
Timestamp: 2025-07-09T17:18:16.685Z
Learning: In packages/core/src/external/ehr/healthie/index.ts, the immunization.cvx_code field is required and non-nullable according to the zod schema validation (z.coerce.string()), so null checks are not needed in the convertImmunizationToFhir method.

Learnt from: thomasyopes
PR: metriport/metriport#4164
File: packages/core/src/external/ehr/healthie/index.ts:939-953
Timestamp: 2025-07-09T17:18:16.685Z
Learning: In packages/core/src/external/ehr/healthie/index.ts, the immunization.cvx_code field is required and non-nullable according to the zod schema validation (z.coerce.string()), so null checks are not needed in the convertImmunizationToFhir method.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.

Learnt from: keshavsaharia
PR: metriport/metriport#4075
File: packages/core/src/external/surescripts/fhir/medication-request.ts:76-83
Timestamp: 2025-06-25T18:42:07.231Z
Learning: In packages/core/src/external/surescripts/fhir/medication-request.ts, the getDispenseNote and getDosageInstruction functions are intentionally identical because the dashboard requires both the note and dosageInstruction fields of MedicationRequest to be populated with detail.directions for proper note display functionality.

Learnt from: thomasyopes
PR: metriport/metriport#4090
File: packages/core/src/command/conversion-fhir/conversion-fhir-cloud.ts:30-30
Timestamp: 2025-06-25T01:55:42.627Z
Learning: In packages/core/src/command/conversion-fhir/conversion-fhir-cloud.ts, the FHIR converter Lambda endpoint is controlled by the team and guaranteed to return valid JSON in the expected Bundle<Resource> format, so JSON.parse() error handling and type validation are not necessary for this specific endpoint.

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: thomasyopes
PR: metriport/metriport#4090
File: packages/core/src/command/conversion-fhir/conversion-fhir-direct.ts:18-25
Timestamp: 2025-06-25T01:56:08.732Z
Learning: In packages/core/src/command/conversion-fhir/conversion-fhir-direct.ts, the ConversionFhirDirect class is designed for local testing purposes and does not require comprehensive error handling for HTTP requests, as confirmed by the user thomasyopes.

Learnt from: lucasdellabella
PR: metriport/metriport#4098
File: packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts:10-22
Timestamp: 2025-06-27T01:50:14.227Z
Learning: In packages/api/src/routes/medical/dtos/tcm-encounter-dto.ts, the patient fields patientData.firstName, patientData.lastName, and patientData.dob are guaranteed to be non-nullable values, so defensive null/undefined checks are not needed when accessing these fields.

Learnt from: thomasyopes
PR: metriport/metriport#4000
File: packages/core/src/external/ehr/athenahealth/index.ts:504-507
Timestamp: 2025-06-11T21:39:26.805Z
Learning: In AthenaHealth write-back (`packages/core/src/external/ehr/athenahealth/index.ts`), only the condition statuses “relapse” and “recurrence” are currently mapped to AthenaHealth problem statuses (“CHRONIC”); other FHIR clinicalStatus values (e.g., “active”, “resolved”, “inactive”, “remission”) are not yet supported.

Learnt from: thomasyopes
PR: metriport/metriport#3936
File: packages/core/src/external/ehr/athenahealth/index.ts:472-482
Timestamp: 2025-06-06T15:37:44.571Z
Learning: In AthenaHealth medication creation, even if medication statements have the same start/stop dates, they should not be deduplicated because there may be relevant differences beyond dates (dosage, administration routes, prescriber info, etc.) that make each statement unique and worth creating separately.

Learnt from: RamilGaripov
PR: metriport/metriport#3976
File: packages/api/src/routes/medical/patient.ts:541-543
Timestamp: 2025-06-18T21:05:22.256Z
Learning: In packages/api/src/routes/medical/patient.ts, inline schema definitions like cohortIdSchema are acceptable and don't need to be moved to separate schema files when the user prefers to keep them inline.

Learnt from: thomasyopes
PR: metriport/metriport#3981
File: packages/core/src/external/ehr/canvas/index.ts:650-657
Timestamp: 2025-06-11T16:56:22.035Z
Learning: In Canvas write-back (`createMedicationStatements`), the intended business logic is to submit only the most recent medication statement; older statements should be ignored.

Learnt from: keshavsaharia
PR: metriport/metriport#4045
File: packages/core/src/external/surescripts/fhir/medication.ts:148-151
Timestamp: 2025-06-18T18:48:28.244Z
Learning: In Surescripts FHIR resource generation, avoid emitting empty strings for FHIR Coding.code fields. Use conditional inclusion patterns (e.g., spreading only when the code value is present and non-empty) to ensure FHIR compliance, as Coding.code MUST NOT be empty according to FHIR standards.

Learnt from: thomasyopes
PR: metriport/metriport#3936
File: packages/core/src/external/ehr/athenahealth/index.ts:936-943
Timestamp: 2025-06-06T13:01:10.264Z
Learning: In the AthenaHealth allergy creation code, only the first reaction is processed intentionally - this is a design decision, not a bug. The code `const snomedCodings = snomedCodingsPairs[0];` deliberately takes only the first reaction from multiple possible reactions.

Learnt from: keshavsaharia
PR: metriport/metriport#4099
File: packages/core/src/external/surescripts/fhir/coverage.ts:37-42
Timestamp: 2025-06-26T06:28:31.490Z
Learning: In packages/core/src/external/surescripts/fhir/coverage.ts, the getInsuranceOrganizationReference function doesn't need ID validation because the Organization resources are always created by getInsuranceOrganization which assigns id: uuidv7(), guaranteeing a valid ID is present.

Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/shared/src/interface/external/ehr/athenahealth/vaccine.ts:4-4
Timestamp: 2025-06-06T16:45:21.766Z
Learning: In Athenahealth EHR integration schemas, property names like "vaccineids" are intentionally preserved to match the external API response format since responses are returned directly without internal transformation or usage.

Learnt from: thomasyopes
PR: metriport/metriport#4039
File: packages/core/src/external/surescripts/fhir/medication.ts:0-0
Timestamp: 2025-06-19T21:51:26.432Z
Learning: In Surescripts FHIR conversion code, numeric validation for fields like detail.quantityDispensed is not considered necessary - the team prefers not to add defensive validation for NaN values in these conversions.

Learnt from: keshavsaharia
PR: metriport/metriport#4045
File: packages/shared/src/interface/external/surescripts/plan-code.ts:1-3
Timestamp: 2025-06-18T17:22:24.597Z
Learning: In packages/shared/src/interface/external/surescripts/plan-code.ts, the getPlanCodeName function should return undefined for invalid plan codes rather than throwing errors, as per user preference for graceful error handling.

Learnt from: lucasdellabella
PR: metriport/metriport#3372
File: packages/infra/lib/hl7-notification-routing-stack/index.ts:35-41
Timestamp: 2025-03-05T06:46:08.168Z
Learning: In the HL7NotificationRoutingStack, it's acceptable for vpnConfigs to be empty, and TypeScript linting will catch cases where it might be undefined, so additional null/emptiness checks aren't necessary.

Learnt from: leite08
PR: metriport/metriport#3463
File: packages/api/src/routes/internal/medical/patient-settings.ts:31-49
Timestamp: 2025-03-19T01:11:01.406Z
Learning: In the Metriport codebase, Zod schema validation errors in routes are intentionally allowed to propagate to the central error handler (packages/api/src/routes/helpers/default-error-handler.ts) rather than being caught with try/catch blocks in individual route handlers. The error handler automatically processes ZodErrors and returns a 400 Bad Request response with formatted validation details.

Learnt from: RamilGaripov
PR: metriport/metriport#3675
File: packages/api/src/routes/internal/hl7/index.ts:0-0
Timestamp: 2025-04-23T06:31:50.128Z
Learning: RamilGaripov prefers using Zod schema validation for parsing and validating all query parameters in routes as it's a cleaner way to write route logic, rather than using separate validation methods like getUUIDFrom().orFail() followed by schema validation.

Learnt from: leite08
PR: metriport/metriport#3940
File: packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts:82-86
Timestamp: 2025-05-31T21:58:28.502Z
Learning: In packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts, the mutable array operations using push() on resourcesMutable and hydratedMutable (lines 82-86 and 100-103) have been explicitly accepted as exceptions to the immutability guidelines after previous discussion.

Learnt from: keshavsaharia
PR: metriport/metriport#4045
File: packages/core/src/external/surescripts/fhir/coverage.ts:0-0
Timestamp: 2025-06-18T18:34:10.489Z
Learning: Coverage resources in Surescripts FHIR conversion are currently excluded from bundles to prevent skewing data lift metrics. The team plans to examine available insurance data thoroughly before including properly structured Coverage resources with mandatory FHIR R4 elements like beneficiary and payor references.

Learnt from: lucasdellabella
PR: metriport/metriport#3866
File: packages/api/src/routes/internal/medical/organization.ts:95-98
Timestamp: 2025-05-27T15:54:47.774Z
Learning: The conversion of the GET `/internal/organization` endpoint from returning a single organization to returning an array of organizations (batch retrieval) in `packages/api/src/routes/internal/medical/organization.ts` was an intentional breaking change planned by the team.

Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:0-0
Timestamp: 2025-05-28T19:20:47.442Z
Learning: In packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.

Learnt from: keshavsaharia
PR: metriport/metriport#4045
File: packages/core/src/external/surescripts/fhir/shared.ts:87-93
Timestamp: 2025-06-18T18:50:40.968Z
Learning: The `getResourceFromResourceMap` function in `packages/core/src/external/surescripts/fhir/shared.ts` works correctly as implemented. The comparison `resourceValue === resourceMap[key]` where `resourceValue = resource[key]` is intentional and functions as designed, despite appearing to compare different types.

Learnt from: leite08
PR: metriport/metriport#0
File: :0-0
Timestamp: 2025-03-05T18:43:30.389Z
Learning: For backmerge PRs at metriport/metriport, only verify two things: (1) that the source branch is `master` and destination branch is `develop`, and (2) that there's a link to at least one PR (usually a "patch" PR) in the description. No need for detailed review comments or updates to the PR description unless there's an issue with these criteria.

Learnt from: leite08
PR: metriport/metriport#3611
File: packages/utils/src/fhir-converter/s3-to-lambda.ts:29-47
Timestamp: 2025-04-05T16:02:02.517Z
Learning: For release PRs (where head branch is `develop` and base branch is `master`), don't suggest code changes as these have already been reviewed in previous PRs. Instead, focus only on checking if the PR description follows the template and practices, and if the PR is pointing to the correct base branch (`master`).

Learnt from: lucasdellabella
PR: metriport/metriport#3907
File: packages/terminology/src/seed/seed-ndc-from-fda.ts:91-113
Timestamp: 2025-05-28T05:28:26.896Z
Learning: On PRs with "release" in the title, only provide very high priority feedback and avoid lower priority suggestions like refactoring or optimization improvements.

Learnt from: leite08
PR: metriport/metriport#3749
File: packages/core/src/command/patient-import/record/create-headers-file.ts:16-27
Timestamp: 2025-04-28T22:57:36.763Z
Learning: Focus improvement suggestions on feature branches rather than release PRs. Release PRs should be treated with higher caution as they're focused on getting tested code into production.

Learnt from: thomasyopes
PR: metriport/metriport#3466
File: packages/api/src/routes/ehr/elation/chart.ts:20-37
Timestamp: 2025-03-17T15:30:34.647Z
Learning: The request body parsing in packages/api/src/routes/ehr/elation/chart.ts is tracked with TODO referencing issue #2170 and will be handled in a separate PR, not in PR #3466.

Learnt from: lucasdellabella
PR: metriport/metriport#0
File: :0-0
Timestamp: 2025-03-14T13:44:44.651Z
Learning: Avoid adding AI-generated summaries to PRs with "RELEASE" in the title.

@thomasyopes thomasyopes added this pull request to the merge queue Jul 9, 2025
Merged via the queue into master with commit bc3e621 Jul 9, 2025
71 checks passed
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.

2 participants