-
Notifications
You must be signed in to change notification settings - Fork 72
Eng 535 athena encounter update #4175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Ref: ENG-535 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
…-athena-encounter-update Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
Ref: ENG-535 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
…-athena-encounter-update Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
WalkthroughThe changes introduce new Athenahealth API methods to fetch and enrich Encounter and Appointment resources, generalize document storage logic to support multiple document types, and centralize S3 key prefix creation. Supporting schemas and types for Athenahealth encounters and appointments are added, and FHIR bundle entry types are renamed for clarity or consistency. Prefix and document key logic is refactored for modularity and reuse. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant AthenaHealthApi
participant AthenaAPI
participant S3
Client->>AthenaHealthApi: getBundleByResourceType / getBundleByResourceId
AthenaHealthApi->>AthenaAPI: Fetch FHIR bundle
AthenaAPI-->>AthenaHealthApi: Return raw FHIR bundle
AthenaHealthApi->>AthenaHealthApi: Convert to strict bundle
AthenaHealthApi->>AthenaHealthApi: dangerouslyAdjustEncountersInBundle
loop For each Encounter in Bundle
AthenaHealthApi->>AthenaAPI: getEncounter (by ID)
AthenaAPI-->>AthenaHealthApi: Return Encounter
AthenaHealthApi->>AthenaAPI: getEncounterSummary
AthenaAPI-->>AthenaHealthApi: Return Summary HTML
AthenaHealthApi->>AthenaAPI: getAppointment (by appointmentId)
AthenaAPI-->>AthenaHealthApi: Return Appointment
AthenaHealthApi->>S3: createOrReplaceDocument (with summary, documentType, etc.)
S3-->>AthenaHealthApi: Store/replace document
AthenaHealthApi->>AthenaHealthApi: Append appointmentTypeId extension to Encounter
end
AthenaHealthApi-->>Client: Return enriched bundle
sequenceDiagram
participant EHRModule
participant DocumentShared
participant S3
EHRModule->>DocumentShared: createOrReplaceDocument({documentType, ...})
DocumentShared->>DocumentShared: Lookup key creation function and content type by documentType
DocumentShared->>S3: Upload document with generated key and correct content type
S3-->>DocumentShared: Acknowledge upload
DocumentShared-->>EHRModule: Complete
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
npm error code ERR_SSL_WRONG_VERSION_NUMBER 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (6)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (4)
🧰 Additional context used📓 Path-based instructions (3)**/*.{js,jsx,ts,tsx}Instructions used from: Sources:
**/*.{ts,tsx}Instructions used from: Sources:
**/*.tsInstructions used from: Sources: 🧠 Learnings (2)📓 Common learnings
packages/core/src/external/ehr/athenahealth/index.ts (49)
⏰ 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). (3)
🔇 Additional comments (17)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Ref: ENG-535 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
There was a problem hiding this 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/core/src/external/ehr/document/command/create-or-replace-document.ts (1)
48-50
: Update logging message to reflect function rename.The logging message still references "createOrReplaceCcda" but should be updated to reflect the new generic function name.
const { log } = out( - `Ehr createOrReplaceCcda - ehr ${ehr} cxId ${cxId} ehrPatientId ${ehrPatientId}` + `Ehr createOrReplaceDocument - ehr ${ehr} cxId ${cxId} ehrPatientId ${ehrPatientId}` );
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
packages/core/src/external/ehr/athenahealth/index.ts
(15 hunks)packages/core/src/external/ehr/bundle/bundle-shared.ts
(1 hunks)packages/core/src/external/ehr/canvas/index.ts
(2 hunks)packages/core/src/external/ehr/document/command/create-or-replace-document.ts
(2 hunks)packages/core/src/external/ehr/document/document-shared.ts
(1 hunks)packages/core/src/external/ehr/elation/index.ts
(2 hunks)packages/core/src/external/ehr/shared.ts
(2 hunks)packages/shared/src/interface/external/ehr/athenahealth/appointment.ts
(1 hunks)packages/shared/src/interface/external/ehr/athenahealth/encounter.ts
(1 hunks)packages/shared/src/interface/external/ehr/athenahealth/index.ts
(1 hunks)packages/shared/src/interface/external/ehr/fhir-resource.ts
(2 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
Useconst
whenever possible
Useasync/await
instead of.then()
Naming: classes, enums: PascalCase
Naming: constants, variables, functions: camelCase
Naming: file names: kebab-case
Naming: Don’t use negative names, likenotEnabled
, preferisDisabled
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 ofin
- i.e.,if (data.link)
notif ('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/canvas/index.ts
packages/shared/src/interface/external/ehr/athenahealth/index.ts
packages/core/src/external/ehr/elation/index.ts
packages/shared/src/interface/external/ehr/athenahealth/appointment.ts
packages/core/src/external/ehr/document/command/create-or-replace-document.ts
packages/shared/src/interface/external/ehr/athenahealth/encounter.ts
packages/core/src/external/ehr/bundle/bundle-shared.ts
packages/shared/src/interface/external/ehr/fhir-resource.ts
packages/core/src/external/ehr/shared.ts
packages/core/src/external/ehr/document/document-shared.ts
packages/core/src/external/ehr/athenahealth/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/canvas/index.ts
packages/shared/src/interface/external/ehr/athenahealth/index.ts
packages/core/src/external/ehr/elation/index.ts
packages/shared/src/interface/external/ehr/athenahealth/appointment.ts
packages/core/src/external/ehr/document/command/create-or-replace-document.ts
packages/shared/src/interface/external/ehr/athenahealth/encounter.ts
packages/core/src/external/ehr/bundle/bundle-shared.ts
packages/shared/src/interface/external/ehr/fhir-resource.ts
packages/core/src/external/ehr/shared.ts
packages/core/src/external/ehr/document/document-shared.ts
packages/core/src/external/ehr/athenahealth/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
, preferisDisabled
- For numeric values, if the type doesn’t convey the unit, add the unit to the name
- Typescript
- Use types
- Prefer
const
instead oflet
- Avoid
any
and casting fromany
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 toundefined
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 (seeprocessAsyncError
andemptyFunction
depending on the case)- Date and Time
- Always use
buildDayjs()
to createdayjs
instances- Prefer
dayjs.duration(...)
to create duration consts and keep them asduration
- 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)
notif ('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
andconsole.error
in packages other than utils, infra and shared,
and try to useout().log
instead- Avoid multi-line logs
- don't send objects as a second parameter to
console.log()
orout().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/canvas/index.ts
packages/shared/src/interface/external/ehr/athenahealth/index.ts
packages/core/src/external/ehr/elation/index.ts
packages/shared/src/interface/external/ehr/athenahealth/appointment.ts
packages/core/src/external/ehr/document/command/create-or-replace-document.ts
packages/shared/src/interface/external/ehr/athenahealth/encounter.ts
packages/core/src/external/ehr/bundle/bundle-shared.ts
packages/shared/src/interface/external/ehr/fhir-resource.ts
packages/core/src/external/ehr/shared.ts
packages/core/src/external/ehr/document/document-shared.ts
packages/core/src/external/ehr/athenahealth/index.ts
🧠 Learnings (12)
📓 Common learnings
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#3882
File: packages/core/src/external/ehr/command/get-bundle-by-resource-type.ts:31-37
Timestamp: 2025-06-05T14:09:59.683Z
Learning: When EHR handlers in mapping objects are set to `undefined` and there are downstream PRs mentioned in the PR objectives, this typically indicates a staged rollout approach where the core structure is implemented first and specific handler implementations follow in subsequent PRs.
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: 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#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.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: 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#3882
File: packages/api/src/external/ehr/athenahealth/command/process-patients-from-appointments.ts:178-180
Timestamp: 2025-05-28T19:06:02.261Z
Learning: In Athena appointments, the `patientid` and `departmentid` fields will always be defined, so null checks are not necessary when calling `createPatientId()` and `createDepartmentId()` on these fields.
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#3891
File: packages/core/src/external/ehr/job/create-resource-diff-bundles/steps/contribute/ehr-contribute-resource-diff-bundles-direct.ts:0-0
Timestamp: 2025-06-20T20:16:15.111Z
Learning: In the codebase, functions prefixed with "dangerously" (like `dangerouslyAddEhrDataSourceExtension`) intentionally mutate input parameters and may use `any` types due to FHIR Resource typing constraints. The "dangerously" prefix serves as a clear indicator that the function violates typical immutability guidelines for specific technical reasons.
packages/core/src/external/ehr/canvas/index.ts (17)
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#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: 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#4164
File: packages/core/src/external/ehr/healthie/index.ts:939-953
Timestamp: 2025-07-09T17:18:16.731Z
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.731Z
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#3981
File: packages/core/src/external/ehr/canvas/index.ts:1376-1379
Timestamp: 2025-06-10T20:14:27.998Z
Learning: Canvas EHR only supports the MedicationStatement statuses "active", "stopped", and "entered-in-error"; it does not accept "completed".
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#4164
File: packages/core/src/external/ehr/healthie/index.ts:1031-1076
Timestamp: 2025-07-09T17:18:28.920Z
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)`.
Learnt from: thomasyopes
PR: metriport/metriport#4164
File: packages/core/src/external/ehr/healthie/index.ts:1031-1076
Timestamp: 2025-07-09T17:18:28.920Z
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: leite08
PR: metriport/metriport#4044
File: packages/api/src/command/medical/tcm-encounter/update-tcm-encounter.ts:23-23
Timestamp: 2025-06-18T04:51:44.941Z
Learning: Error messages should be fixed, stable, and non-dynamic. Dynamic data like IDs should be moved to the `additionalInfo` property of MetriportError instead of being interpolated into the error message string.
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/api/src/external/ehr/canvas/command/bundle/fetch-ehr-bundle.ts:62-72
Timestamp: 2025-04-23T18:57:54.964Z
Learning: In the metriport codebase, factory implementations like `fetchCanvasBundle` intentionally let errors bubble up to the caller rather than handling them at the factory function level.
Learnt from: leite08
PR: metriport/metriport#3749
File: packages/api/src/command/medical/patient/patient-import/get.ts:70-74
Timestamp: 2025-04-28T23:10:42.561Z
Learning: Error messages should have static messages. Dynamic data like IDs should be added to MetriportError's `additionalInfo` property rather than interpolated into the error message string.
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#3383
File: packages/api/src/routes/ehr-internal/canvas/internal/patient.ts:10-24
Timestamp: 2025-03-05T21:42:32.929Z
Learning: The processPatientsFromAppointments endpoint in the Canvas API is intentionally designed to be asynchronous (fire-and-forget pattern). The endpoint returns a 200 OK response immediately after initiating the process, without waiting for it to complete. Error handling is handled through the .catch() method with processAsyncError rather than awaiting the promise.
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#4044
File: packages/api/src/command/medical/tcm-encounter/update-tcm-encounter.ts:23-23
Timestamp: 2025-06-18T04:51:44.941Z
Learning: Error messages should be fixed, stable, and non-dynamic. Dynamic data like IDs should be moved to the `additionalInfo` property of MetriportError instead of being interpolated into the error message string.
Learnt from: leite08
PR: metriport/metriport#3463
File: packages/api/src/command/medical/patient/settings/create-patient-settings.ts:202-204
Timestamp: 2025-03-19T13:41:19.957Z
Learning: In the Metriport codebase, when using `capture.error` or `capture.message` functions, the order of properties in the `extra` parameter is important because Sentry may trim data beyond its payload limit. The most critical information (usually `cxId`) should be placed first, while less important data (like `facilityId`) should be placed last.
packages/shared/src/interface/external/ehr/athenahealth/index.ts (9)
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#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: 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: 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#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#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#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: 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.
packages/core/src/external/ehr/elation/index.ts (14)
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#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: 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#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#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#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#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#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: 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#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#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.
packages/shared/src/interface/external/ehr/athenahealth/appointment.ts (11)
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: 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#3882
File: packages/api/src/external/ehr/athenahealth/command/process-patients-from-appointments.ts:178-180
Timestamp: 2025-05-28T19:06:02.261Z
Learning: In Athena appointments, the `patientid` and `departmentid` fields will always be defined, so null checks are not necessary when calling `createPatientId()` and `createDepartmentId()` on these fields.
Learnt from: thomasyopes
PR: metriport/metriport#3960
File: packages/lambdas/src/ehr/get-appointments.ts:36-44
Timestamp: 2025-06-05T16:28:12.424Z
Learning: In packages/lambdas/src/ehr/get-appointments.ts, date validation is not required for the convertToGetAppointmentsRequest function because the input is controlled and dates will always be valid.
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: thomasyopes
PR: metriport/metriport#4164
File: packages/core/src/external/ehr/healthie/index.ts:1031-1076
Timestamp: 2025-07-09T17:18:28.920Z
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:939-953
Timestamp: 2025-07-09T17:18:16.731Z
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.731Z
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#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.
packages/core/src/external/ehr/document/command/create-or-replace-document.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: 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/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: 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#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#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: 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#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#3608
File: packages/core/src/external/ehr/resource-diff/steps/compute/ehr-compute-resource-diff-cloud.ts:52-59
Timestamp: 2025-04-19T13:15:42.469Z
Learning: Error handling in Metriport's EHR components: Factory and handler classes like `EhrComputeResourceDiffCloud` should not throw exceptions (like MetriportError) during batch processing operations. They should use other error handling approaches instead of throwing.
packages/shared/src/interface/external/ehr/athenahealth/encounter.ts (12)
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: 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: 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#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#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#4164
File: packages/core/src/external/ehr/healthie/index.ts:1031-1076
Timestamp: 2025-07-09T17:18:28.920Z
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.920Z
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)`.
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#4164
File: packages/core/src/external/ehr/healthie/index.ts:939-953
Timestamp: 2025-07-09T17:18:16.731Z
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: 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: thomasyopes
PR: metriport/metriport#4164
File: packages/core/src/external/ehr/healthie/index.ts:939-953
Timestamp: 2025-07-09T17:18:16.731Z
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.
packages/core/src/external/ehr/bundle/bundle-shared.ts (18)
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: 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#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/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#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: 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#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#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: 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: 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#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#3427
File: packages/lambdas/src/ehr-sync-patient.ts:31-33
Timestamp: 2025-03-11T19:12:22.472Z
Learning: In this codebase, a specific logging pattern is used: `console.log` is used for early logging before context is available, then a prefixed logger (created with `prefixedLog`) is initialized after parsing data to include contextual information (like ehr, cxId, practiceId, patientId) in all subsequent log messages.
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#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#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#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#3869
File: packages/core/src/external/fhir/export/string/shared/deny.ts:17-20
Timestamp: 2025-05-21T16:30:39.421Z
Learning: In the Metriport codebase, even when parameters are currently unused in a function implementation (as indicated by eslint-disable comments), the team prefers to keep the original parameter names without underscore prefixes to maintain API compatibility for clients, as the implementation details might change in the future.
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/fhir-resource.ts (15)
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: 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#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: 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: 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#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/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#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#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#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: 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#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#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.
packages/core/src/external/ehr/shared.ts (21)
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: 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#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#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: 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#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: 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#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#3869
File: packages/core/src/external/fhir/export/string/shared/deny.ts:17-20
Timestamp: 2025-05-21T16:30:39.421Z
Learning: In the Metriport codebase, even when parameters are currently unused in a function implementation (as indicated by eslint-disable comments), the team prefers to keep the original parameter names without underscore prefixes to maintain API compatibility for clients, as the implementation details might change in the future.
Learnt from: thomasyopes
PR: metriport/metriport#3427
File: packages/lambdas/src/ehr-sync-patient.ts:31-33
Timestamp: 2025-03-11T19:12:22.472Z
Learning: In this codebase, a specific logging pattern is used: `console.log` is used for early logging before context is available, then a prefixed logger (created with `prefixedLog`) is initialized after parsing data to include contextual information (like ehr, cxId, practiceId, patientId) in all subsequent log messages.
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#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: thomasyopes
PR: metriport/metriport#3891
File: packages/core/src/external/ehr/job/create-resource-diff-bundles/steps/contribute/ehr-contribute-resource-diff-bundles-direct.ts:0-0
Timestamp: 2025-06-20T20:16:15.111Z
Learning: In the codebase, functions prefixed with "dangerously" (like `dangerouslyAddEhrDataSourceExtension`) intentionally mutate input parameters and may use `any` types due to FHIR Resource typing constraints. The "dangerously" prefix serves as a clear indicator that the function violates typical immutability guidelines for specific technical reasons.
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#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#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#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#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#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/document/document-shared.ts (10)
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#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: 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#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#3550
File: packages/api/src/external/commonwell/__tests__/patient.test.ts:5-5
Timestamp: 2025-04-01T19:59:22.396Z
Learning: The file at `packages/api/src/aws/app-config.ts` contains domain feature flags (not AWS AppConfig specific functionality) and is planned to be moved to the domain folder in packages/core in a future PR.
Learnt from: thomasyopes
PR: metriport/metriport#3885
File: packages/core/src/external/surescripts/client.ts:170-180
Timestamp: 2025-06-13T21:41:01.744Z
Learning: In packages/core/src/external/surescripts/client.ts, the leading slash in "/from_surescripts" used with listFileNamesWithPrefix for replica lookups is intentional, despite appearing inconsistent with other replica path references that don't use leading slashes.
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#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: 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.
packages/core/src/external/ehr/athenahealth/index.ts (48)
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#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: 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#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: lucasdellabella
PR: metriport/metriport#4098
File: packages/api/src/command/medical/tcm-encounter/get-tcm-encounters.ts:88-93
Timestamp: 2025-06-27T01:50:29.111Z
Learning: The pagination logic in packages/api/src/command/medical/tcm-encounter/get-tcm-encounters.ts uses conditional sort order (ASC when toItem is present for forward pagination, DESC otherwise for backward pagination) and inclusive bounds (>= and <=) which is intentional for proper bidirectional pagination functionality. Changing to always use ASC order or exclusive bounds would break this pagination pattern.
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: 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#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#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: 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#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#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#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: 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#3608
File: packages/core/src/external/ehr/bundle/create-resource-diff-bundles/steps/compute/ehr-compute-resource-diff-bundles-local.ts:40-54
Timestamp: 2025-04-23T18:58:11.038Z
Learning: In the metriport codebase, factory implementations like `EhrComputeResourceDiffBundlesLocal` intentionally let errors bubble up to the caller rather than handling them at the factory function level.
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#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: leite08
PR: metriport/metriport#3940
File: packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts:60-73
Timestamp: 2025-05-31T21:29:39.196Z
Learning: In search-consolidated.ts, the user prefers to let errors bubble up from concurrent search operations (Promise.all) rather than catching them explicitly with try-catch blocks. Errors from searchFhirResources and searchDocuments should be allowed to propagate up the call stack.
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#3882
File: packages/api/src/external/ehr/athenahealth/command/process-patients-from-appointments.ts:178-180
Timestamp: 2025-05-28T19:06:02.261Z
Learning: In Athena appointments, the `patientid` and `departmentid` fields will always be defined, so null checks are not necessary when calling `createPatientId()` and `createDepartmentId()` on these fields.
Learnt from: thomasyopes
PR: metriport/metriport#3883
File: packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/start-jobs-across-ehrs.ts:38-46
Timestamp: 2025-05-28T19:42:17.301Z
Learning: Athena patient IDs necessarily contain a "." character - this is a required format for all valid Athena patient IDs.
Learnt from: thomasyopes
PR: metriport/metriport#3891
File: packages/core/src/external/ehr/job/create-resource-diff-bundles/steps/contribute/ehr-contribute-resource-diff-bundles-direct.ts:0-0
Timestamp: 2025-06-20T20:16:15.111Z
Learning: In the codebase, functions prefixed with "dangerously" (like `dangerouslyAddEhrDataSourceExtension`) intentionally mutate input parameters and may use `any` types due to FHIR Resource typing constraints. The "dangerously" prefix serves as a clear indicator that the function violates typical immutability guidelines for specific technical reasons.
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: thomasyopes
PR: metriport/metriport#3383
File: packages/api/src/routes/ehr-internal/canvas/internal/patient.ts:10-24
Timestamp: 2025-03-05T21:42:32.929Z
Learning: The processPatientsFromAppointments endpoint in the Canvas API is intentionally designed to be asynchronous (fire-and-forget pattern). The endpoint returns a 200 OK response immediately after initiating the process, without waiting for it to complete. Error handling is handled through the .catch() method with processAsyncError rather than awaiting the promise.
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: thomasyopes
PR: metriport/metriport#3754
File: packages/core/src/external/ehr/healthie/link-patient/healthie-link-patient-cloud.ts:17-25
Timestamp: 2025-04-30T21:00:14.857Z
Learning: In the Healthie integration, errors from the SQS client in the link-patient functionality are allowed to bubble up to the caller rather than being caught and re-thrown with additional context at each level.
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: lucasdellabella
PR: metriport/metriport#3866
File: packages/core/src/command/hl7v2-subscriptions/hl7v2-roster-generator.ts:142-151
Timestamp: 2025-05-27T16:10:48.223Z
Learning: In packages/core/src/command/hl7v2-subscriptions/hl7v2-roster-generator.ts, the user prefers to let axios errors bubble up naturally rather than adding try-catch blocks that re-throw with MetriportError wrappers, especially when the calling code already has retry mechanisms in place via simpleExecuteWithRetries.
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: leite08
PR: metriport/metriport#3749
File: packages/api/src/command/medical/patient/patient-import/get.ts:70-74
Timestamp: 2025-04-28T23:10:42.561Z
Learning: Error messages should have static messages. Dynamic data like IDs should be added to MetriportError's `additionalInfo` property rather than interpolated into the error message string.
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: 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#3754
File: packages/api/src/external/ehr/healthie/shared.ts:31-40
Timestamp: 2025-04-30T21:05:32.787Z
Learning: For the `createContacts` function in the Healthie integration, returning an empty contacts array is preferred over throwing an error when no contact information (email or phone) is available for a patient.
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: leite08
PR: metriport/metriport#4044
File: packages/api/src/command/medical/tcm-encounter/update-tcm-encounter.ts:23-23
Timestamp: 2025-06-18T04:51:44.941Z
Learning: Error messages should be fixed, stable, and non-dynamic. Dynamic data like IDs should be moved to the `additionalInfo` property of MetriportError instead of being interpolated into the error message string.
Learnt from: leite08
PR: metriport/metriport#4044
File: packages/api/src/command/medical/tcm-encounter/update-tcm-encounter.ts:23-23
Timestamp: 2025-06-18T04:51:44.941Z
Learning: Error messages should be fixed, stable, and non-dynamic. Dynamic data like IDs should be moved to the `additionalInfo` property of MetriportError instead of being interpolated into the error message string.
Learnt from: leite08
PR: metriport/metriport#3857
File: packages/core/src/command/consolidated/search/fhir-resource/search-lexical.ts:67-82
Timestamp: 2025-05-28T02:51:35.779Z
Learning: In the search-lexical.ts file, the user prefers to bubble up JSON parsing errors rather than catching and logging them. When processing FHIR resources from OpenSearch results, errors should be thrown and allowed to propagate up the call stack instead of being caught and silently ignored.
Learnt from: leite08
PR: metriport/metriport#3979
File: packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts:197-212
Timestamp: 2025-06-07T18:30:25.152Z
Learning: In search operations within search-consolidated.ts, the user prefers not to worry about partial runs and doesn't want explicit error handling with try-catch blocks for batch processing failures. They prefer to let errors bubble up naturally rather than catching them explicitly during search operations.
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#3873
File: packages/core/src/external/ehr/command/get-appointments/ehr-get-appointments-cloud.ts:40-43
Timestamp: 2025-05-29T16:53:26.064Z
Learning: The EHR get-appointments Lambda function is designed to always return parseable JSON responses, so additional error handling for JSON.parse() is not required when processing its results.
Learnt from: thomasyopes
PR: metriport/metriport#3754
File: packages/api/src/external/ehr/healthie/command/get-patient-from-appointment.ts:22-24
Timestamp: 2025-04-30T20:59:34.247Z
Learning: The Healthie API's `getAppointment` method already validates that appointments have attendees and throws an error if none are found. The return type `AppointmentWithAttendee` reflects this guarantee, making additional validation unnecessary when accessing `attendees[0]`.
Learnt from: thomasyopes
PR: metriport/metriport#3960
File: packages/lambdas/src/ehr/get-appointments.ts:36-44
Timestamp: 2025-06-05T16:28:12.424Z
Learning: In packages/lambdas/src/ehr/get-appointments.ts, date validation is not required for the convertToGetAppointmentsRequest function because the input is controlled and dates will always be valid.
Learnt from: thomasyopes
PR: metriport/metriport#3771
File: packages/api/src/external/ehr/healthie/command/process-patients-from-appointments.ts:121-128
Timestamp: 2025-05-01T16:15:20.823Z
Learning: In the Healthie EHR system, patient IDs are globally unique across practices, making `patientId` alone sufficient for deduplication without needing to include `practiceId`.
🧬 Code Graph Analysis (3)
packages/core/src/external/ehr/bundle/bundle-shared.ts (2)
packages/core/src/util/config.ts (1)
Config
(11-342)packages/core/src/external/ehr/shared.ts (1)
CreatePrefixParams
(299-306)
packages/core/src/external/ehr/shared.ts (1)
packages/shared/src/interface/external/ehr/source.ts (1)
EhrSource
(9-9)
packages/core/src/external/ehr/document/document-shared.ts (3)
packages/core/src/external/ehr/shared.ts (2)
CreatePrefixParams
(299-306)createPrefix
(308-317)packages/core/src/external/aws/s3.ts (1)
S3Utils
(140-570)packages/shared/src/interface/external/ehr/source.ts (1)
EhrSource
(9-9)
⏰ 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). (3)
- GitHub Check: check-pr / lint-build-test
- GitHub Check: check-pr / lint-build-test
- GitHub Check: Analyze (javascript)
🔇 Additional comments (23)
packages/core/src/external/ehr/canvas/index.ts (2)
704-704
: LGTM: Improved consistency by using static string literal.Converting the template literal to a regular string literal is appropriate here since there's no dynamic interpolation, and it aligns with the coding guideline that error messages should be static.
929-929
: LGTM: Improved consistency by using static string literal.Converting the template literal to a regular string literal is appropriate here since there's no dynamic interpolation, and it aligns with the coding guideline that error messages should be static.
packages/core/src/external/ehr/shared.ts (2)
299-317
: LGTM: Excellent refactoring to centralize prefix creation logic.The new
CreatePrefixParams
type andcreatePrefix
function provide a clean, reusable utility for generating consistent S3 prefixes. The function follows functional programming principles and the default value forjobId
("latest") is sensible. This centralization will help prevent inconsistencies and reduce code duplication across the EHR integration modules.
749-749
: LGTM: Explicit return type improves code clarity.Making the
Promise<void>
return type explicit enhances the function signature's readability and makes the asynchronous nature more obvious to consumers.packages/shared/src/interface/external/ehr/athenahealth/index.ts (1)
15-15
: LGTM: Appropriate expansion of the public interface.Adding the encounter export follows the established pattern in this file and makes the encounter types accessible to consumers of the Athenahealth interface module, supporting the new encounter-related functionality introduced in the core AthenaHealthApi class.
packages/core/src/external/ehr/elation/index.ts (2)
37-38
: LGTM: Import changes align with document type generalization.The replacement of CCDA-specific imports with generic document handling imports is consistent with the PR objective to generalize document storage logic for multiple document types.
352-364
: LGTM: Function call updated correctly for generic document handling.The changes properly migrate from the CCDA-specific
createOrReplaceCcda
to the genericcreateOrReplaceDocument
with explicitDocumentType.CCDA
parameter. The variable rename frompayload
toccda
improves code clarity.packages/shared/src/interface/external/ehr/athenahealth/appointment.ts (1)
3-11
: LGTM: Clean appointment schema definitions.The new appointment schemas are well-structured and follow established patterns in the codebase. The field names appropriately preserve the external Athenahealth API format, which is consistent with the team's approach for EHR integrations.
packages/shared/src/interface/external/ehr/fhir-resource.ts (1)
20-23
: LGTM: Improved naming convention for FHIR bundle entry types.The renaming from "Wrapper" to "BundleEntry" significantly improves code clarity and better describes the purpose of these schemas. The changes are consistent across all related types and schema references.
Also applies to: 26-26, 39-47
packages/core/src/external/ehr/bundle/bundle-shared.ts (1)
8-8
: LGTM: Well-executed refactoring to shared prefix creation utilities.The changes successfully centralize prefix creation logic by importing and using the shared
createPrefix
function. TheCreateBundlePrefixParams
type properly extendsCreatePrefixParams
with the bundle-specificresourceId
field, and the implementation correctly delegates to the shared utility while maintaining the existing functionality.Also applies to: 13-34
packages/shared/src/interface/external/ehr/athenahealth/encounter.ts (1)
1-14
: LGTM: Well-structured encounter schemas for Athenahealth integration.The new encounter schemas are clean and follow established patterns in the codebase. The use of
z.coerce.string()
forappointmentid
appropriately handles potential type coercion from the external API, and the field names preserve the external API format as expected for Athenahealth integrations.packages/core/src/external/ehr/document/document-shared.ts (2)
65-71
: LGTM! Clean mapping design.The
createKeyAndExtensionMap
provides a clean, extensible way to associate document types with their key creation functions and MIME types, enabling type-safe document handling.
73-75
: LGTM! Appropriate S3Utils factory function.The factory function correctly creates an S3Utils instance with the configured AWS region, following good encapsulation practices.
packages/core/src/external/ehr/document/command/create-or-replace-document.ts (3)
52-63
: LGTM! Excellent dynamic key creation logic.The use of
createKeyAndExtensionMap
with proper validation for invalid document types provides a clean, type-safe way to handle different document types. The error handling withBadRequestError
is appropriate for invalid input.
65-72
: LGTM! Proper content type handling.The dynamic content type setting using
createKeyAndExtension.extension
correctly handles different document types, replacing the previous hardcoded CCDA content type.
74-87
: LGTM! Improved error handling and context.The error handling properly includes the dynamic extension in the error context and uses generic "EHR document" terminology. The
context
field correctly reflects the new function name.packages/core/src/external/ehr/athenahealth/index.ts (7)
34-39
: LGTM: Import additions are well-organized.The new imports for encounter/appointment schemas and document handling functionality follow the established patterns and properly support the new methods.
Also applies to: 83-87, 102-103, 121-122
168-170
: Extension URL constant follows FHIR standards.The
encounterAppointmentExtensionUrl
constant is properly structured according to FHIR extension URL conventions. This allows storing appointment type ID information as an extension on Encounter resources, which is a valid FHIR pattern.
498-530
: LGTM: New resource fetching methods follow established patterns.The
getEncounter
,getEncounterSummary
, andgetAppointment
methods are well-implemented with:
- Proper input validation and ID normalization
- Consistent error handling with appropriate error types
- Schema validation for type safety
- Single result validation to ensure data integrity
All methods follow the established patterns used throughout the AthenaHealth API client.
Also applies to: 532-557, 1701-1733
1917-2012
: Complex but well-structured encounter processing method.The
dangerouslyAdjustEncountersInBundle
method effectively enriches Encounter resources with appointment data and creates corresponding documents. Key strengths:
- Parallel processing for performance optimization
- Proper filtering for Encounter resources with valid IDs
- Comprehensive error handling that appropriately ignores expected errors
- Document creation using the generalized document handling system
- Extension addition to link appointment type IDs
The "dangerously" prefix correctly indicates that this method mutates the input bundle, which aligns with the established pattern for such functions.
1544-1555
: Good integration of encounter processing in bundle methods.The integration of
dangerouslyAdjustEncountersInBundle
into bothgetBundleByResourceType
andgetResourceBundleByResourceId
is well-placed:
- Called after bundle validation but before return
- Ensures consistent encounter enrichment across both retrieval methods
- Maintains the existing method flow and error handling
This ensures that encounter data is enhanced with appointment information and documents are created regardless of how bundles are retrieved.
Also applies to: 1637-1648
2052-2054
: Helper method follows established pattern.The
stripEncounterId
method correctly follows the same pattern as other ID manipulation methods (stripPatientId
,stripDepartmentId
, etc.) and properly handles encounter ID normalization.
726-726
: Good consistency improvement in error messages.Removing template literals from error messages improves consistency and aligns with the coding guideline preference for static error messages with dynamic data in
additionalInfo
.Also applies to: 1256-1256, 1331-1331, 1413-1413, 1999-1999
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/core/src/external/ehr/athenahealth/index.ts (1)
1919-2012
: Consider performance implications of the encounter enrichment process.The method enriches every encounter in the bundle by making additional API calls, which could result in significant overhead for bundles with many encounters. However, this appears intentional based on the PR objectives for Athena monitoring. The error handling appropriately catches expected errors and continues processing, while collecting unexpected errors for monitoring.
The "dangerously" prefix correctly indicates that this method mutates the input bundle, which aligns with similar patterns in the codebase.
Consider implementing batching or caching strategies if this enrichment process becomes a performance bottleneck in production, especially for patients with many encounters.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/core/src/external/ehr/athenahealth/index.ts
(16 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
Useconst
whenever possible
Useasync/await
instead of.then()
Naming: classes, enums: PascalCase
Naming: constants, variables, functions: camelCase
Naming: file names: kebab-case
Naming: Don’t use negative names, likenotEnabled
, preferisDisabled
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 ofin
- i.e.,if (data.link)
notif ('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/athenahealth/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/athenahealth/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
, preferisDisabled
- For numeric values, if the type doesn’t convey the unit, add the unit to the name
- Typescript
- Use types
- Prefer
const
instead oflet
- Avoid
any
and casting fromany
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 toundefined
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 (seeprocessAsyncError
andemptyFunction
depending on the case)- Date and Time
- Always use
buildDayjs()
to createdayjs
instances- Prefer
dayjs.duration(...)
to create duration consts and keep them asduration
- 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)
notif ('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
andconsole.error
in packages other than utils, infra and shared,
and try to useout().log
instead- Avoid multi-line logs
- don't send objects as a second parameter to
console.log()
orout().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/athenahealth/index.ts
🧠 Learnings (2)
📓 Common learnings
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#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#3882
File: packages/core/src/external/ehr/command/get-bundle-by-resource-type.ts:31-37
Timestamp: 2025-06-05T14:09:59.683Z
Learning: When EHR handlers in mapping objects are set to `undefined` and there are downstream PRs mentioned in the PR objectives, this typically indicates a staged rollout approach where the core structure is implemented first and specific handler implementations follow in subsequent PRs.
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: 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: 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#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#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/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#3882
File: packages/api/src/external/ehr/athenahealth/command/process-patients-from-appointments.ts:178-180
Timestamp: 2025-05-28T19:06:02.261Z
Learning: In Athena appointments, the `patientid` and `departmentid` fields will always be defined, so null checks are not necessary when calling `createPatientId()` and `createDepartmentId()` on these fields.
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#3891
File: packages/core/src/external/ehr/job/create-resource-diff-bundles/steps/contribute/ehr-contribute-resource-diff-bundles-direct.ts:0-0
Timestamp: 2025-06-20T20:16:15.111Z
Learning: In the codebase, functions prefixed with "dangerously" (like `dangerouslyAddEhrDataSourceExtension`) intentionally mutate input parameters and may use `any` types due to FHIR Resource typing constraints. The "dangerously" prefix serves as a clear indicator that the function violates typical immutability guidelines for specific technical reasons.
packages/core/src/external/ehr/athenahealth/index.ts (48)
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: 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: 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#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: lucasdellabella
PR: metriport/metriport#4098
File: packages/api/src/command/medical/tcm-encounter/get-tcm-encounters.ts:88-93
Timestamp: 2025-06-27T01:50:29.111Z
Learning: The pagination logic in packages/api/src/command/medical/tcm-encounter/get-tcm-encounters.ts uses conditional sort order (ASC when toItem is present for forward pagination, DESC otherwise for backward pagination) and inclusive bounds (>= and <=) which is intentional for proper bidirectional pagination functionality. Changing to always use ASC order or exclusive bounds would break this pagination pattern.
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: 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: 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#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: 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#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#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#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: 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#3608
File: packages/core/src/external/ehr/bundle/create-resource-diff-bundles/steps/compute/ehr-compute-resource-diff-bundles-local.ts:40-54
Timestamp: 2025-04-23T18:58:11.038Z
Learning: In the metriport codebase, factory implementations like `EhrComputeResourceDiffBundlesLocal` intentionally let errors bubble up to the caller rather than handling them at the factory function level.
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#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: leite08
PR: metriport/metriport#3940
File: packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts:60-73
Timestamp: 2025-05-31T21:29:39.196Z
Learning: In search-consolidated.ts, the user prefers to let errors bubble up from concurrent search operations (Promise.all) rather than catching them explicitly with try-catch blocks. Errors from searchFhirResources and searchDocuments should be allowed to propagate up the call stack.
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#3882
File: packages/api/src/external/ehr/athenahealth/command/process-patients-from-appointments.ts:178-180
Timestamp: 2025-05-28T19:06:02.261Z
Learning: In Athena appointments, the `patientid` and `departmentid` fields will always be defined, so null checks are not necessary when calling `createPatientId()` and `createDepartmentId()` on these fields.
Learnt from: thomasyopes
PR: metriport/metriport#3883
File: packages/api/src/external/ehr/shared/job/bundle/create-resource-diff-bundles/start-jobs-across-ehrs.ts:38-46
Timestamp: 2025-05-28T19:42:17.301Z
Learning: Athena patient IDs necessarily contain a "." character - this is a required format for all valid Athena patient IDs.
Learnt from: thomasyopes
PR: metriport/metriport#3891
File: packages/core/src/external/ehr/job/create-resource-diff-bundles/steps/contribute/ehr-contribute-resource-diff-bundles-direct.ts:0-0
Timestamp: 2025-06-20T20:16:15.111Z
Learning: In the codebase, functions prefixed with "dangerously" (like `dangerouslyAddEhrDataSourceExtension`) intentionally mutate input parameters and may use `any` types due to FHIR Resource typing constraints. The "dangerously" prefix serves as a clear indicator that the function violates typical immutability guidelines for specific technical reasons.
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: thomasyopes
PR: metriport/metriport#3383
File: packages/api/src/routes/ehr-internal/canvas/internal/patient.ts:10-24
Timestamp: 2025-03-05T21:42:32.929Z
Learning: The processPatientsFromAppointments endpoint in the Canvas API is intentionally designed to be asynchronous (fire-and-forget pattern). The endpoint returns a 200 OK response immediately after initiating the process, without waiting for it to complete. Error handling is handled through the .catch() method with processAsyncError rather than awaiting the promise.
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: thomasyopes
PR: metriport/metriport#3754
File: packages/core/src/external/ehr/healthie/link-patient/healthie-link-patient-cloud.ts:17-25
Timestamp: 2025-04-30T21:00:14.857Z
Learning: In the Healthie integration, errors from the SQS client in the link-patient functionality are allowed to bubble up to the caller rather than being caught and re-thrown with additional context at each level.
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: lucasdellabella
PR: metriport/metriport#3866
File: packages/core/src/command/hl7v2-subscriptions/hl7v2-roster-generator.ts:142-151
Timestamp: 2025-05-27T16:10:48.223Z
Learning: In packages/core/src/command/hl7v2-subscriptions/hl7v2-roster-generator.ts, the user prefers to let axios errors bubble up naturally rather than adding try-catch blocks that re-throw with MetriportError wrappers, especially when the calling code already has retry mechanisms in place via simpleExecuteWithRetries.
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: leite08
PR: metriport/metriport#3749
File: packages/api/src/command/medical/patient/patient-import/get.ts:70-74
Timestamp: 2025-04-28T23:10:42.561Z
Learning: Error messages should have static messages. Dynamic data like IDs should be added to MetriportError's `additionalInfo` property rather than interpolated into the error message string.
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: 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#3754
File: packages/api/src/external/ehr/healthie/shared.ts:31-40
Timestamp: 2025-04-30T21:05:32.787Z
Learning: For the `createContacts` function in the Healthie integration, returning an empty contacts array is preferred over throwing an error when no contact information (email or phone) is available for a patient.
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: leite08
PR: metriport/metriport#4044
File: packages/api/src/command/medical/tcm-encounter/update-tcm-encounter.ts:23-23
Timestamp: 2025-06-18T04:51:44.941Z
Learning: Error messages should be fixed, stable, and non-dynamic. Dynamic data like IDs should be moved to the `additionalInfo` property of MetriportError instead of being interpolated into the error message string.
Learnt from: leite08
PR: metriport/metriport#4044
File: packages/api/src/command/medical/tcm-encounter/update-tcm-encounter.ts:23-23
Timestamp: 2025-06-18T04:51:44.941Z
Learning: Error messages should be fixed, stable, and non-dynamic. Dynamic data like IDs should be moved to the `additionalInfo` property of MetriportError instead of being interpolated into the error message string.
Learnt from: leite08
PR: metriport/metriport#3857
File: packages/core/src/command/consolidated/search/fhir-resource/search-lexical.ts:67-82
Timestamp: 2025-05-28T02:51:35.779Z
Learning: In the search-lexical.ts file, the user prefers to bubble up JSON parsing errors rather than catching and logging them. When processing FHIR resources from OpenSearch results, errors should be thrown and allowed to propagate up the call stack instead of being caught and silently ignored.
Learnt from: leite08
PR: metriport/metriport#3979
File: packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts:197-212
Timestamp: 2025-06-07T18:30:25.152Z
Learning: In search operations within search-consolidated.ts, the user prefers not to worry about partial runs and doesn't want explicit error handling with try-catch blocks for batch processing failures. They prefer to let errors bubble up naturally rather than catching them explicitly during search operations.
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#3873
File: packages/core/src/external/ehr/command/get-appointments/ehr-get-appointments-cloud.ts:40-43
Timestamp: 2025-05-29T16:53:26.064Z
Learning: The EHR get-appointments Lambda function is designed to always return parseable JSON responses, so additional error handling for JSON.parse() is not required when processing its results.
Learnt from: thomasyopes
PR: metriport/metriport#3754
File: packages/api/src/external/ehr/healthie/command/get-patient-from-appointment.ts:22-24
Timestamp: 2025-04-30T20:59:34.247Z
Learning: The Healthie API's `getAppointment` method already validates that appointments have attendees and throws an error if none are found. The return type `AppointmentWithAttendee` reflects this guarantee, making additional validation unnecessary when accessing `attendees[0]`.
Learnt from: thomasyopes
PR: metriport/metriport#3960
File: packages/lambdas/src/ehr/get-appointments.ts:36-44
Timestamp: 2025-06-05T16:28:12.424Z
Learning: In packages/lambdas/src/ehr/get-appointments.ts, date validation is not required for the convertToGetAppointmentsRequest function because the input is controlled and dates will always be valid.
Learnt from: thomasyopes
PR: metriport/metriport#3771
File: packages/api/src/external/ehr/healthie/command/process-patients-from-appointments.ts:121-128
Timestamp: 2025-05-01T16:15:20.823Z
Learning: In the Healthie EHR system, patient IDs are globally unique across practices, making `patientId` alone sufficient for deduplication without needing to include `practiceId`.
⏰ 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). (3)
- GitHub Check: check-pr / lint-build-test
- GitHub Check: check-pr / lint-build-test
- GitHub Check: Analyze (javascript)
🔇 Additional comments (8)
packages/core/src/external/ehr/athenahealth/index.ts (8)
34-39
: LGTM! New imports are correctly structured.The new imports for encounter, appointment, and document handling functionality are properly organized and follow the existing import patterns.
Also applies to: 83-87, 102-104, 121-122
168-169
: LGTM! Extension URL export is appropriate.The encounter appointment extension URL export follows HL7 FHIR standards and will be used to link encounters with appointment type information.
500-532
: LGTM! getEncounter method follows established patterns.The method properly validates that exactly one encounter is returned and includes appropriate error handling for both missing and multiple encounters.
534-559
: LGTM! getEncounterSummary method is well-implemented.The method correctly fetches encounter summary HTML and follows the same patterns as other API methods in the class.
728-728
: LGTM! Error message formatting is now consistent.The string formatting changes align with the consistent error message style used throughout the codebase.
Also applies to: 1258-1258, 1333-1333, 1415-1415
1703-1735
: LGTM! getAppointment method follows established patterns.The method properly validates that exactly one appointment is returned and includes appropriate error handling, consistent with other similar methods in the class.
546-556
: LGTM! Bundle enrichment integration is properly placed.The calls to
dangerouslyAdjustEncountersInBundle
are appropriately placed after bundle conversion and will enrich encounter resources with additional context before returning the bundle.Also applies to: 639-649
2052-2054
: LGTM! stripEncounterId method follows naming conventions.The method correctly strips the encounter ID prefix and follows the same pattern as other ID manipulation methods in the class.
Ref: ENG-535 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
…-athena-encounter-update Signed-off-by: Thomas Yopes <thomasyopes@Mac.attlocal.net>
Issues:
Description
Testing
Release Plan
Summary by CodeRabbit
Summary by CodeRabbit
New Features
Refactor
Bug Fixes
Documentation