-
Notifications
You must be signed in to change notification settings - Fork 67
RELEASE ENG-268 Updates to GlobalSearch Plumbing / ENG-198 ECW Backend #3892
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
refs. metriport/metriport-internal#198 Signed-off-by: Syed Husain <syed@metriport.com>
Ref: ENG-198 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-199 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-199 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
refs. metriport/metriport-internal#198 Signed-off-by: Syed Husain <syed@metriport.com>
Ref: ENG-198 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
…triport into 198-ecw-patientflow Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
… 198-ecw-v2 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref eng-41 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
- group OS bulk errors to Sentry - store individual errors in NDJON when run from utils Ref eng-41 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
- move getConsolidated to core - reorg OS code on core Ref eng-268 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref eng-268 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref: ENG-198 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref: ENG-198 Ref: #1040 Signed-off-by: Thomas Yopes <thomasyopes@Thomass-MBP.attlocal.net>
Ref eng-268 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
ENG-268 Review FHIR resources to string
198 ecw v2
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: 40
🔭 Outside diff range comments (3)
packages/core/src/external/opensearch/file/file-remover-direct.ts (1)
21-21
: 🛠️ Refactor suggestionConsider adding error handling for the delete operation.
The OpenSearch delete operation could fail and should be wrapped in a try/catch block to provide better error handling and logging.
async remove(entryId: string): Promise<void> { const { indexName, endpoint, username, password } = this.config; const { log } = out(`OSFileRemover.remove - entryId ${entryId}`); const auth = { username, password }; const client = new Client({ node: endpoint, auth }); - await client.delete({ index: indexName, id: entryId }); - log(`Successfully deleted ${entryId}`); + try { + await client.delete({ index: indexName, id: entryId }); + log(`Successfully deleted ${entryId}`); + } catch (error) { + const errorMsg = `Failed to delete entry ${entryId} from OpenSearch`; + log(errorMsg); + throw new Error(errorMsg, { cause: error }); + } }packages/core/src/external/opensearch/semantic/semantic-searcher.ts (1)
20-24
: 💡 Verification agent🧩 Analysis chain
Mismatch between JSDoc and runtime validation makes
0
an impossible but documented valueThe JSDoc states that both
maxNumberOfResults
andsimilarityThreshold
accept a lower bound of 0, yet the validators throw formaxNumberOfResults < 1
andsimilarityThreshold <= 0
.
This silent contract breach will surface only at runtime and is hard to diagnose.- /** From 0 to 10_000, optional, defaults to 100 */ + /** From 1 to 10_000, optional, defaults to 100 */ ... - /** From 0 to 1, optional, defaults to 0.2 */ + /** From (0, 1], optional, defaults to 0.2 */or loosen the guards, e.g.
- if (maxNumberOfResults < 1) { - throw new BadRequestError("maxNumberOfResults cannot be less than 1"); - } + if (maxNumberOfResults < 0) { + throw new BadRequestError("maxNumberOfResults cannot be negative"); + }Align the two sides before this ships.
Also applies to: 78-85, 87-94
🏁 Script executed:
#!/bin/bash set -e # Show declarations and runtime checks for maxNumberOfResults rg -n "maxNumberOfResults" -C3 packages/core/src/external/opensearch/semantic/semantic-searcher.ts # Show declarations and runtime checks for similarityThreshold rg -n "similarityThreshold" -C3 packages/core/src/external/opensearch/semantic/semantic-searcher.tsLength of output: 3339
Align JSDoc bounds with runtime validation
The JSDoc for both parameters currently documents a lower bound of 0, but the actual validators enforce:
maxNumberOfResults ≥ 1
similarityThreshold ∈ (0, 1]
This mismatch means setting either to 0 (as the docs allow) will throw at runtime.
Locations to fix:
- packages/core/src/external/opensearch/semantic/semantic-searcher.ts, lines 20–24 (JSDoc for the two fields)
Suggested diff:
- /** From 0 to 10_000, optional, defaults to 100 */ + /** From 1 to 10_000, optional, defaults to 100 */ maxNumberOfResults?: number | undefined; - /** From 0 to 1, optional, defaults to 0.2 */ + /** From (0, 1], optional, defaults to 0.2 */ similarityThreshold?: number | undefined;Alternatively, if you prefer to allow 0, adjust the guards in
validateMaxNumberOfResults
andvalidateSimilarityThreshold
to match the documented bounds.packages/core/src/command/ai-brief/filter.ts (1)
409-415
:⚠️ Potential issueCase-sensitive filter may leak stale lab reports
nonLabReports
omits atoLowerCase()
call, so any category value like “Laboratory Data” will slip through, defeating the whole purpose of the filter and potentially bloating the AI payload.- const nonLabReports = reports.filter(report => !report.category?.includes("laboratory data")); + const nonLabReports = reports.filter( + report => + !( + report.category && + typeof report.category === "string" && + report.category.toLowerCase().includes("laboratory data") + ) + );
🧹 Nitpick comments (64)
packages/core/src/external/html/remove-tags.ts (2)
52-52
: Use optional chaining for cleaner code.As suggested by the static analysis tool, you can simplify the conditional logging using optional chaining.
- log && log(`Removing HTML tags...`); + log?.(`Removing HTML tags...`);🧰 Tools
🪛 Biome (1.9.4)
[error] 52-52: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
18-32
: Consider extracting regex patterns to constants.For better maintainability and reusability, consider extracting the com 6D47 piled regex patterns to module-level constants with descriptive names.
+ // Module-level regex constants for better reusability + const REGEX_GENERIC_WORDS = new RegExp( + `(${genericStopWords.map(w => w.toLowerCase()).join("|")})`, + "g" + ); + const REGEX_HTML_TAGS = new RegExp( + `</?(${htmlStopWords.map(w => w.toLowerCase()).join("|")})(\\s.*?)?/?>`, + "g" + ); + const REGEX_FORMATTING = /(__+|--+)/g; + const REGEX_MARKUP_ATTRIBUTES = /((\w+(:\w+)?)(:\w+)?="(?<content>[^"]+?)")/g; + const REGEX_ADDITIONAL_MARKUP = /<(\w+(:\w+)?)(\s*|\s(?<content>[^>]+?))\/?>/g; + const REGEX_CLOSING_MARKUP = /<\/(\w+(:\w+)?)>/g; + const REGEX_NEWLINES_TABS = /"|(\n\n)|\n|\t|\r|<!/g; + const REGEX_MULTIPLE_SPACES = /(\s\s+)/g; - const regexGenericWords = new RegExp( - `(${genericStopWords.map(w => w.toLowerCase()).join("|")})`, - "g" - ); - // removes the tag w/ attributes, but without content - const regexHtml = new RegExp( - `</?(${htmlStopWords.map(w => w.toLowerCase()).join("|")})(\\s.*?)?/?>`, - "g" - ); - const regexFormatting = new RegExp(/(__+|--+)/g); - const regexMarkupAttributes = new RegExp(/((\w+(:\w+)?)(:\w+)?="(?<content>[^"]+?)")/g); - const regexAdditionalMarkup = new RegExp(/<(\w+(:\w+)?)(\s*|\s(?<content>[^>]+?))\/?>/g); - const regexClosingMarkup = new RegExp(/<\/(\w+(:\w+)?)>/g); - const regexNewlinesTabs = new RegExp(/"|(\n\n)|\n|\t|\r|<!/g); - const regexMultipleSpaces = new RegExp(/(\s\s+)/g);packages/core/src/external/fhir/normalization/resources/encounter.ts (1)
83-85
: Good technical debt tracking with TODO comment.The TODO comment appropriately identifies potential code duplication that should be investigated. This is excellent practice for maintaining code quality.
I can help investigate whether
isUsefulDisplay()
can replaceisDisplayUseful()
. Would you like me to search the codebase for similar functions and analyze their compatibility?#!/bin/bash # Search for similar display utility functions ast-grep --pattern 'function isUsefulDisplay($$$) { $$$ }' ast-grep --pattern 'function isDisplayUseful($$$) { $$$ }' rg -A 5 "isUsefulDisplay|isDisplayUseful"packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-factory.ts (1)
4-11
: Address the TODO comment for dynamic implementation selection.The factory function is well-implemented using appropriate patterns, but the TODO comment (ENG-268) indicates incomplete work. Consider whether this should be completed before merging or if there's a plan to address it in a follow-up.
The commented code shows the intended design for environment-based selection between
SearchConsolidatedDirect
andSearchConsolidatedLambda
implementations.Would you like me to help implement the dynamic selection based on environment configuration, or is this intentionally deferred to a future task?
packages/utils/src/shared/sentry.ts (2)
15-23
: Consider making the Sentry configuration more flexible.The current implementation hardcodes the sample rates, which reduces flexibility for different development scenarios. Consider accepting configuration parameters to make this more reusable.
Apply this diff to make the function more configurable:
-export function initSentry() { +export function initSentry({ + sampleRate = 1.0, + tracesSampleRate = 0, +}: { + sampleRate?: number; + tracesSampleRate?: number; +} = {}) { Sentry.init({ dsn: sentryDsn, enabled: sentryDsn != null, environment: getEnvType(), - sampleRate: 1.0, // error sample rate - tracesSampleRate: 0, // transaction sample rate + sampleRate, // error sample rate + tracesSampleRate, // transaction sample rate }); }
7-14
: Consider programmatic enforcement of development-only usage.The comment warns against pushing code that enables Sentry in scripts, but this could be enforced programmatically to prevent accidents.
Consider adding a runtime check:
/** * Function to initialize Sentry for rare cases we want to test sending events to Sentry. * * Note: this should only be called while developing, don't push code to the repo enabling * Sentry in scripts that might send lots of messages to Sentry. * * @see packages/api/src/sentry.ts * @see packages/lambdas/src/shared/capture.ts */ export function initSentry() { + if (getEnvType() === "production") { + throw new Error("initSentry should not be called in production environment"); + } Sentry.init({packages/core/src/external/opensearch/semantic/hybrid-create.ts (1)
1-1
: Address the TODO comment for index creation implementation.This file currently contains only a commented JSON template. The TODO indicates this needs to be converted to executable code for creating the hybrid search index.
Would you like me to help implement the index creation code or open a new issue to track this task? The JSON template looks well-structured for a hybrid search index with k-NN vector capabilities.
packages/api/src/routes/ehr/eclinicalworks/patient.ts (1)
35-35
: Improve response structure consistency.The response returns a bare
patientId
value. Consider wrapping it in an object for better API consistency and future extensibility.-return res.status(httpStatus.OK).json(patientId); +return res.status(httpStatus.OK).json({ patientId });Also applies to: 63-63
packages/api/src/routes/ehr/eclinicalworks/routes/dash.ts (1)
17-17
: Consider using a more descriptive variable name.The variable
documentSkipPathsForEclinicalworksIdCheck
could be shortened to improve readability while maintaining clarity.-const documentSkipPathsForEclinicalworksIdCheck = [documentDownloadUrlRegex]; +const skipPatientIdCheckPaths = [documentDownloadUrlRegex];Then update the usage on line 34:
- documentSkipPathsForEclinicalworksIdCheck + skipPatientIdCheckPathspackages/api/src/external/ehr/eclinicalworks/shared.ts (1)
26-35
: Consider error handling for client creation.The
createEClinicalWorksClient
function looks clean, but consider adding error handling around theEClinicalWorksApi.create()
call to provide more context if client creation fails.export async function createEClinicalWorksClient( perPracticeParams: EClinicalWorksPerPracticeParams ): Promise<EClinicalWorksApi> { const { environment } = getEClinicalWorksEnv(); - return await EClinicalWorksApi.create({ - practiceId: perPracticeParams.practiceId, - environment, - authToken: perPracticeParams.authToken, - }); + try { + return await EClinicalWorksApi.create({ + practiceId: perPracticeParams.practiceId, + environment, + authToken: perPracticeParams.authToken, + }); + } catch (error) { + throw new MetriportError("Failed to create EClinicalWorks client", error, { + practiceId: perPracticeParams.practiceId, + environment, + }); + }packages/core/src/external/fhir/export/string/shared/narrative.ts (1)
5-5
: Consider using a more robust HTML filtering approach.The current array-based filtering approach has potential issues:
- The regex construction could be inefficient for larger arrays
- It doesn't handle case variations or attributes in div tags
- The regex is recreated on every function call
Consider these improvements:
-const filterFromDiv = ['<div xmlns="http://www.w3.org/1999/xhtml">', "<div>", "</div>", "<div/>"]; +const DIV_TAG_REGEX = /<\/?div[^>]*>/gi;Then in the function:
-const filteredDiv = narrative.div?.replace(new RegExp(filterFromDiv.join("|"), "g"), ""); +const filteredDiv = narrative.div?.replace(DIV_TAG_REGEX, "");packages/core/src/external/fhir/export/string/shared/deny.ts (1)
17-20
: Consider adding TODO comment for stub function.The
isAllowedSystem
function is currently a stub that always returnstrue
. This could be problematic if used in production without proper implementation.Consider adding a TODO comment to make the stub nature explicit:
+// TODO: Implement proper system filtering logic // eslint-disable-next-line @typescript-eslint/no-unused-vars export function isAllowedSystem(value: string | undefined): boolean { return true; }
packages/core/src/external/fhir/export/string/resources/coverage.ts (2)
107-118
: Apply optional chaining for cleaner code.The static analysis tool correctly identifies that the nested property access can be simplified using optional chaining.
Apply this diff to improve readability:
- exception && - exception - .map(ex => { + exception + ?.map(ex => { const exComponents = [ formatCodeableConcept({ concept: ex.type, label: "Type", isDebug }), formatPeriod({ period: ex.period, label: "Period", isDebug }), ].filter(Boolean); const exStr = exComponents.join(FIELD_SEPARATOR); return exStr.length > 0 ? (isDebug ? `Exception: ${exStr}` : exStr) : undefined; }) - .filter(Boolean) - .join(FIELD_SEPARATOR), + ?.filter(Boolean) + ?.join(FIELD_SEPARATOR),🧰 Tools
🪛 Biome (1.9.4)
[error] 107-118: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
56-59
: Consider uncommenting useful fields or removing commented code.Several potentially useful fields are commented out (subscriberId, order, network, subrogation). Consider either implementing these fields if they provide value for coverage representation, or removing the commented code to keep the codebase clean.
packages/core/src/external/fhir/resources/diagnostic-report.ts (1)
17-20
: Consider tracking the TODO for content type handling.The TODO comment identifies important future enhancements for handling different content types and downloading external attachments. Consider creating a backlog item to track this enhancement.
Would you like me to create an issue to track the TODO for content type-based conversion and external attachment handling?
packages/core/src/external/fhir/export/string/resources/encounter.ts (1)
13-48
: Good refactoring with one consistency suggestion.The EncounterToString updates follow the established patterns well:
- Proper isDebug parameter support
- Good use of
emptyIfDenied
for status filtering- Appropriate
hasMinimumData
pattern to return undefined when no meaningful data- Clean object-based parameter passing to formatting functions
Consider using the
formatPeriod
utility function for the period formatting (lines 40-44) to maintain consistency with other formatters:- if (encounter.period) { - const start = encounter.period.start ?? "unknown"; - const end = encounter.period.end ?? "ongoing"; - parts.push(isDebug ? `Period: ${start} to ${end}` : `${start} to ${end}`); - } + const periodStr = formatPeriod({ period: encounter.period, label: "Period", isDebug }); + if (periodStr) parts.push(periodStr);This would align with the shared formatting approach used throughout the codebase.
packages/utils/src/fhir/ai-brief/build-slim-bundle.ts (1)
18-20
: Fix typo in JSDoc comment.There's a typo in the comment.
-/** - * Script compare the output of the buildSlimmerPayload funcion with the original bundle. - */ +/** + * Script to compare the output of the buildSlimmerPayload function with the original bundle. + */packages/core/src/external/fhir/export/string/resources/communication.ts (2)
35-38
: Consider documenting the commented subject field.The commented-out subject field handling suggests planned functionality. Consider adding a TODO comment explaining why it's commented out or when it might be enabled.
- // if (communication.subject) { - // const subjectStr = formatReferences([communication.subject], "Subject"); - // if (subjectStr) parts.push(subjectStr); - // } + // TODO: Subject field handling - determine if needed for Communication string representation + // if (communication.subject) { + // const subjectStr = formatReferences([communication.subject], "Subject"); + // if (subjectStr) parts.push(subjectStr); + // }
94-111
: Complex payload processing looks correct but could benefit from helper function.The payload processing logic correctly handles multiple content types, but the nested structure makes it somewhat complex to follow. Consider extracting the payload formatting logic into a separate helper function for better readability.
Example refactor:
private formatPayloadContent(payload: CommunicationPayload, isDebug?: boolean): string | undefined { const { contentString, contentAttachment, contentReference } = payload; const components = [ contentString && (isDebug ? `Content: ${contentString}` : contentString), formatAttachment({ attachment: contentAttachment, isDebug }), formatReference({ reference: contentReference, label: "Content Ref", isDebug }), ].filter(Boolean); return components.length > 0 ? components.join(FIELD_SEPARATOR) : undefined; }packages/core/src/external/opensearch/lexical/lexical-search.ts (1)
15-15
: Fix regex construction to use literal notation.Use a regex literal instead of the RegExp constructor for better readability and static analysis.
- const actualQuery = query.replace(new RegExp(`^\\$\\s*`, "g"), ""); + const actualQuery = query.replace(/^\$\s*/g, "");🧰 Tools
🪛 Biome (1.9.4)
[error] 15-15: Use a regular expression literal instead of the RegExp constructor.
Regular expression literals avoid some escaping required in a string literal, and are easier to analyze statically.
Safe fix: Use a literal notation instead.(lint/complexity/useRegexLiterals)
packages/core/src/external/fhir/export/string/shared/duration.ts (1)
19-19
: Use strict equality operator.The coding guidelines specify using strict equality operator
===
instead of abstract equality==
. If you need to check for bothnull
andundefined
, consider using!= null
to be more explicit about the intent.- if (value != undefined) parts.push(value.toString()); + if (value !== undefined) parts.push(value.toString());Or if checking for both null and undefined is intended:
- if (value != undefined) parts.push(value.toString()); + if (value != null) parts.push(value.toString());packages/core/src/external/fhir/export/string/shared/__tests__/codeable-concept.test.ts (1)
15-21
: Test logic needs correction.The test expects
undefined
for an empty concept, but the test creates a concept with an emptycoding
array, which may not be the same as a truly empty concept.Consider testing both scenarios explicitly:
- it("returns empty string if no concept", () => { - const concept: CodeableConcept = { coding: [] }; - const res = formatCodeableConcept({ concept }); - expect(res).toBeUndefined(); - }); + it("returns undefined if no concept", () => { + const res = formatCodeableConcept({ concept: undefined }); + expect(res).toBeUndefined(); + }); + + it("returns undefined if concept has empty coding array", () => { + const concept: CodeableConcept = { coding: [] }; + const res = formatCodeableConcept({ concept }); + expect(res).toBeUndefined(); + });packages/core/src/external/fhir/export/string/resources/related-person.ts (2)
23-26
: Consider removing commented code or documenting the plan.The commented-out patient reference code should either be removed if not needed or documented with a TODO explaining when it will be implemented.
- // if (person.patient) { - // const patientStr = formatReferences([person.patient], "Patient"); - // if (patientStr) parts.push(patientStr); - // } + // TODO: Add patient reference formatting when cross-references are supported
54-86
: Extensive commented code should be addressed.Large blocks of commented code for photo and communication handling should either be implemented, removed, or moved to a TODO with clear implementation plans.
Consider creating separate issues for these features:
- // if (person.photo) { - // const photos = person.photo - // .map(photo => { - // const contentType = photo.contentType ? `Content Type: ${photo.contentType}` : undefined; - // const url = photo.url ? `URL: ${photo.url}` : undefined; - // const size = photo.size ? `Size: ${photo.size}` : undefined; - // const hash = photo.hash ? `Hash: ${photo.hash}` : undefined; - // return [contentType, url, size, hash].filter(Boolean).join(FIELD_SEPARATOR); - // }) - // .filter(Boolean); - - // if (photos.length > 0) { - // parts.push(`Photos: ${photos.join(FIELD_SEPARATOR)}`); - // hasMinimumData = true; - // } - // } - - // if (person.communication) { - // const communications = person.communication - // .map(comm => { - // const language = comm.language - // ? formatCodeableConcepts([comm.language], "Language") - // : undefined; - // const preferred = comm.preferred ? `Preferred: ${comm.preferred}` : undefined; - // return [language, preferred].filter(Boolean).join(FIELD_SEPARATOR); - // }) - // .filter(Boolean); - - // if (communications.length > 0) { - // parts.push(`Communications: ${communications.join(FIELD_SEPARATOR)}`); - // hasMinimumData = true; - // } - // } + // TODO: Implement photo formatting (issue #XXX) + // TODO: Implement communication formatting (issue #XXX)packages/core/src/external/fhir/export/string/resources/medication-administration.ts (1)
58-61
: Consider removing or documenting commented subject reference code.Similar to the RelatedPerson file, commented code should be addressed with clear documentation or removal.
- // if (administration.subject) { - // const subjectStr = formatReferences([administration.subject], "Subject"); - // if (subjectStr) parts.push(subjectStr); - // } + // TODO: Add subject reference when cross-references are supportedpackages/core/src/external/fhir/export/string/resources/medication-dispense.ts (1)
49-54
: Clean up commented-out code blocks.There are commented-out blocks for
subject
anddaysSupply
fields. Consider either implementing these fields or removing the commented code to improve maintainability.- // if (dispense.subject) { - // const subjectStr = formatReferences({ references: [dispense.subject], label: "Subject", isDebug }); - // if (subjectStr) { - // parts.push(subjectStr); - // } - // } - // if (dispense.daysSupply) { - // const daysSupplyStr = formatQuantity({ quantity: dispense.daysSupply, label: "Days Supply", isDebug }); - // if (daysSupplyStr) { - // parts.push(daysSupplyStr); - // } - // }Also applies to: 101-106
packages/core/src/command/consolidated/search/fhir-resource/ingest-lexical.ts (2)
30-38
: Unused Promise result – clarify intent or drop it
Promise.all
returns an array with two results, but the delete promise is ignored after destructuring.
If the intention is merely to fire-and-forget the delete, consider:
- Awaiting it first to guarantee the cleanup happened before ingestion, or
- Dropping it from
Promise.all
and triggering it without awaiting (with proper error handling) to make that intent explicit.- const [convertedResources] = await Promise.all([ - getConsolidatedAsText({ patient }), - ingestor.delete({ cxId: patient.cxId, patientId: patient.id }), - ]); + await ingestor.delete({ cxId: patient.cxId, patientId: patient.id }); + const convertedResources = await getConsolidatedAsText({ patient });This also avoids allocating an unnecessary array.
63-71
: Config helper duplication – consider single responsibility
getConfigs()
is re-implemented in multiple OpenSearch‐related modules. Extracting it into a shared util (e.g.,searchConfig.ts
) would:• Remove duplication
• Ensure changes (e.g., env var renames) are propagated automatically
• Improve testabilityNot urgent, but advisable before additional search components appear.
packages/core/src/external/fhir/export/string/resources/medication.ts (1)
63-81
: Ingredient reference ignored – possible data lossYou removed the
itemReference
branch (commented out). Some Medication resources populateingredient.itemReference
instead ofitemCodeableConcept
.
Consider falling back to the reference when the codeable concept is absent to avoid silently omitting ingredients.- const item = formatCodeableConcept({ - concept: ingredient.itemCodeableConcept, - label: "Ingredient", - isDebug, - }); + const item = + formatCodeableConcept({ + concept: ingredient.itemCodeableConcept, + label: "Ingredient", + isDebug, + }) ?? + formatReferences({ + references: [ingredient.itemReference], + label: "Ingredient", + isDebug, + });packages/core/src/external/fhir/export/string/resources/family-member-history.ts (3)
20-23
: Consider surfacingstatus
only when meaningful
history.status
is pushed unchanged, which may emit low–information codes like"entered-in-error"
to end-users. Usuallystatus
is helpful only for debugging; for consumer-facing strings you may want to:
- Skip neutral values (
"completed"
,"unknown"
) or- Localise / prettify them (e.g.
"active"
→"Active"
).
If the intention is a user-visible sentence rather than raw debug, consider mapping the enum to human-readable text or hide it behindisDebug
.
50-53
: Avoid wrappingundefined
inside arrays
formatCodeableConcepts({ concepts: [history.sex], … })
still creates an array with one element whenhistory.sex
isundefined
, causingformatCodeableConcepts
to iterate once and allocate unnecessarily.
A small guard avoids this overhead and reduces the risk of false “array has length” checks:-if (history.sex) { - const sexStr = formatCodeableConcepts({ concepts: [history.sex], label: "Sex", isDebug }); +if (history.sex) { + const sexStr = formatCodeableConcepts({ concepts: [history.sex], label: "Sex", isDebug });Or:
const sexStr = formatCodeableConcepts({ concepts: history.sex ? [history.sex] : undefined, label: "Sex", isDebug, });
73-75
: Ambiguous deceased flag
Whenhistory.deceasedBoolean
istrue
the literal string"Deceased"
is appended, but in debug mode there is no label/context.
Consider outputting"Deceased: true"
(or"Deceased"
only whenisDebug
is off) to keep the pattern consistent with the other labelled fields.packages/core/src/external/fhir/export/string/shared/timing.ts (3)
24-25
: Parentheses precedence makes intent slightly opaque
const eventsWithLabel = eventsStr && isDebug ? …
relies on&&
binding tighter than?:
.
Although correct, a reader may need to double-take. An explicit ternary reads clearer:const eventsWithLabel = eventsStr ? isDebug ? `Events: ${eventsStr}` : eventsStr : undefined;
37-45
:formatTimingRepeat
is a pure formatter – mark itconst
and move outside?
The helper closes over no mutable state and is not part of the public API.
Extracting it to its own module or marking itconst formatTimingRepeat = (…) => { … }
makes the intent (pure, reusable) explicit and avoids hoisting surprises.
112-113
: Unit hard-coded as string
formatNumeric({ value: offset, unit: "minutes", … })
duplicates the literal"minutes"
.
Consider exporting aTIME_UNITS
enum / const to avoid typos and enable future localisation.packages/core/src/external/opensearch/file/file-ingestor-direct.ts (2)
18-20
: Left-over regex constants are now unused
regexQuotesNewlinesTabs
andregexMultipleSpaces
were kept after refactor but are no longer referenced.
Remove them (and their related tests) to avoid dead code and maintainers wondering “why are these here?”.
154-168
:makeSureIndexExists
leaks as public API
The method was downgraded fromprivate
topublic
but is still an internal helper; exposing it broadens the public surface unnecessarily.
If external access isn’t required, restoreprivate
or at leastprotected
visibility.packages/core/src/external/fhir/export/string/bundle-to-string.ts (1)
78-79
: Remove the TODO comment for Patient resource.The TODO comment suggests Patient should be removed, but Patient is actually included in the bundle construction logic (line 113 in the map). This comment might be outdated or misleading.
RelatedPerson: RelatedPerson; - // TODO REMOVE THIS Patient: Patient;
packages/core/src/external/fhir/export/string/resources/consent.ts (2)
40-43
: Consider removing or implementing commented patient reference code.The commented code for patient reference formatting should either be implemented if needed or removed if not required. Leaving commented code can create confusion about intended functionality.
If patient reference is needed:
if (consent.patient) { const patientStr = formatReference({ reference: consent.patient, label: "Patient", isDebug, }); if (patientStr) parts.push(patientStr); }Otherwise, remove the commented block.
189-204
: Remove commented sub-provision code or implement it.The extensive commented code for sub-provisions suggests this was either planned functionality or removed code. Consider either implementing it properly with the new formatting patterns or removing it entirely.
If sub-provisions are needed, they should use the current formatting patterns:
if (provision.provision) { const subProvisions = provision.provision .map(subProvision => { const components = [ subProvision.type && (isDebug ? `Type: ${subProvision.type}` : subProvision.type), formatPeriod({ period: subProvision.period, label: "Period", isDebug }), formatCodeableConcepts({ concepts: subProvision.code, label: "Code", isDebug }), ].filter(Boolean); return components.join(FIELD_SEPARATOR); }) .filter(Boolean); if (subProvisions.length > 0) { const subProvisionsStr = subProvisions.join(FIELD_SEPARATOR); provisionParts.push(isDebug ? `Sub-provisions: ${subProvisionsStr}` : subProvisionsStr); } }packages/core/src/external/fhir/export/string/resources/composition.ts (2)
42-45
: Consider removing or documenting commented code.The commented-out subject field processing should either be removed if no longer needed or documented with a reason for being commented out.
- // if (composition.subject) { - // const subjectStr = formatReferences([composition.subject], "Subject"); - // if (subjectStr) parts.push(subjectStr); - // }If this code will be needed later, consider adding a TODO comment explaining why it's temporarily disabled.
99-101
: Remove commented code or document its purpose.Similar to the subject field, this commented confidentiality code should be cleaned up.
- // if (composition.confidentiality) { - // parts.push(`Confidentiality: ${composition.confidentiality}`); - // }packages/core/src/external/fhir/export/string/resources/procedure.ts (1)
29-34
: Consider cleaning up commented subject processing.The commented subject field processing should be removed if not needed or documented with a TODO if it will be implemented later.
- // if (procedure.subject) { - // const subjectStr = formatReferences([procedure.subject], "Subject"); - // if (subjectStr) { - // parts.push(subjectStr); - // } - // }packages/core/src/external/fhir/export/string/shared/annotation.ts (2)
35-37
: Add parentheses to avoid precedence ambiguities
&&
has higher precedence than the ternary?:
, so the current expression is technically correct, but the intent is not immediately obvious at a glance. Wrapping the&&
clause with parentheses makes the condition explicit and improves readability.- authorString && isDebug ? `Author: ${authorString}` : authorString, + (authorString && isDebug) ? `Author: ${authorString}` : authorString,
15-18
: Consider forwardinglabel
into the per-annotation formatter
formatAnnotations
forwards onlyannotation
andisDebug
toformatAnnotation
.
If the caller supplies alabel
, each inner annotation will never see it, so per-annotation output can’t be labelled in debug mode. If the desired behaviour is to prefix each annotation with the same label (e.g., “Note 1: …, Note 2: …”), forward the label—or an auto-generated label—downstream.- .map(annotation => formatAnnotation({ annotation, isDebug })) + .map(annotation => formatAnnotation({ annotation, label, isDebug }))packages/core/src/external/opensearch/semantic/semantic-searcher.ts (1)
42-45
: Instantiate the OpenSearch client once, not per searchCreating a new
Client
for everysearch()
call incurs TLS handshake & connection-pool overhead and prevents connection reuse. Consider:-class OpenSearchSemanticSearcher { - constructor(readonly config: OpenSearchSemanticSearcherConfig) {} +class OpenSearchSemanticSearcher { + private readonly client: Client; + constructor(readonly config: OpenSearchSemanticSearcherConfig) { + this.client = new Client({ + node: config.endpoint, + auth: { username: config.username, password: config.password }, + }); + }…and drop the per-call instantiation.
packages/core/src/external/fhir/export/string/shared/human-name.ts (1)
25-27
:lodash/uniq
is overkill here—dedupe with aSet
uniq
adds ~24 kB (min) to the bundle. A single-liner withSet
is faster and tree-shakable:-const dedupedNames = uniq(formattedNames); +const dedupedNames = [...new Set(formattedNames)];Same behaviour, lighter footprint.
packages/core/src/external/fhir/export/string/shared/telecom.ts (1)
43-44
: Address commented-out code.The commented lines for
use
andrank
fields should either be implemented or removed. Leaving commented code reduces maintainability and can cause confusion.Consider either:
- Implementing the missing fields if they're needed:
- // use && isDebug ? `Use: ${use}` : use, - // rank && isDebug ? `Rank: ${rank}` : rank, + telecom.use && isDebug ? `Use: ${telecom.use}` : telecom.use, + telecom.rank && isDebug ? `Rank: ${telecom.rank}` : telecom.rank,
- Or removing them entirely if they're not needed:
- // use && isDebug ? `Use: ${use}` : use, - // rank && isDebug ? `Rank: ${rank}` : rank,packages/api/src/routes/ehr/eclinicalworks/auth/middleware.ts (1)
12-12
: Consider making the query parameter constant more descriptive.The constant name
tokenEhrPatientIdQueryParam
could be more specific to eClinicalWorks to avoid potential conflicts.Consider renaming for clarity:
-export const tokenEhrPatientIdQueryParam = "eclinicalworksPatientIdFromToken"; +export const ECLINICALWORKS_TOKEN_PATIENT_ID_QUERY_PARAM = "eclinicalworksPatientIdFromToken";This follows the coding guidelines for constant naming (using SCREAMING_SNAKE_CASE for constants).
packages/core/src/external/opensearch/shared/bulk.ts (1)
4-5
: Consider making BulkRequest type more specific.The current
BulkRequest
type usesPartial<Record<BulkOperation, { _id: string }>>
which allows for empty objects. Consider if this is intentional or if at least one operation should be required.-export type BulkRequest = Partial<Record<BulkOperation, { _id: string }>>; +export type BulkRequest = Record<BulkOperation, { _id: string }>;This would ensure at least one operation is always present, but only apply this if it aligns with the expected usage patterns.
packages/core/src/external/fhir/export/string/resources/diagnostic-report.ts (1)
23-26
: Consider removing commented code or adding TODO.There's commented-out code for
basedOn
field. Consider either removing it if it's not needed or adding a TODO comment explaining why it's commented.- // if (report.basedOn) { - // const basedOnStr = formatReferences(report.basedOn, "Based On"); - // if (basedOnStr) parts.push(basedOnStr); - // } + // TODO: Add basedOn field formatting when requirements are clarified + // if (report.basedOn) { + // const basedOnStr = formatReferences({ references: report.basedOn, label: "Based On", isDebug }); + // if (basedOnStr) parts.push(basedOnStr); + // }packages/api/src/routes/internal/medical/patient-consolidated.ts (1)
49-140
: Well-implemented route with good transaction handling.The route properly validates parameters, uses database transactions for consistency, and includes comprehensive logging. The dry run functionality is valuable for testing.
Consider addressing the scalability concerns mentioned in the comments about moving to a queue-based design for larger patient volumes.
Would you like me to help track the TODO item on line 61 about moving this to an ops/internal command?
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)
34-34
: Extract magic string to a constant.The magic string "<!empty!>" should be extracted to a named constant for better maintainability and clarity.
+const EMPTY_CODE_PLACEHOLDER = "<!empty!>"; + export function formatCodeableConcept({ concept, label, skipInternalCodes, isDebug = defaultIsDebug, }: { concept: CodeableConcept | undefined; label?: string; skipInternalCodes?: boolean | undefined; isDebug?: boolean | undefined; }): string | undefined { if (!concept) return undefined; const textPre = emptyIfDenied(concept.text); const text = textPre ? textPre.trim() : undefined; - const emptyCode = "<!empty!>"; + const emptyCode = EMPTY_CODE_PLACEHOLDER;
55-61
: Consider simplifying string building logic.The string building logic could be more concise and functional. Consider using array methods for cleaner code.
- let codingStr = ""; - const values = Object.values(codingMap); - const sortedValues = values.sort(); - for (const coding of sortedValues) { - const separator = codingStr.length > 0 ? ` ${SEP_BETWEEN_CODING} ` : ""; - codingStr = codingStr + separator + coding; - } + const codingStr = Object.values(codingMap) + .sort() + .join(` ${SEP_BETWEEN_CODING} `);packages/core/src/external/fhir/export/string/shared/coding.ts (1)
86-88
: Consider improving function naming and add JSDoc.The
isInternalCoding
function could benefit from better documentation about what constitutes an "internal" coding.+/** + * Checks if a coding uses an internal code system that should be filtered out. + * Internal systems start with the OID prefix "urn:oid:1.2.840." + * @param coding - The FHIR coding to check + * @returns true if the coding uses an internal code system + */ function isInternalCoding(coding: Coding): boolean { return coding.system?.startsWith(INTERNAL_CODE_SYSTEM) ?? false; }packages/api/src/external/ehr/eclinicalworks/command/sync-patient.ts (2)
91-96
: Improve error message specificity.The error message "Invalid token source" could be more descriptive to help with debugging.
if (token.data.source !== eclinicalworksDashSource) { - throw new MetriportError("Invalid token source", undefined, { + throw new MetriportError(`Invalid token source, expected ${eclinicalworksDashSource}`, undefined, { tokenId, source: token.data.source, + expectedSource: eclinicalworksDashSource, }); }
98-105
: Improve error message specificity.The error message "Invalid token practiceId" could be more descriptive.
if (tokenPracticeId !== practiceId) { - throw new MetriportError("Invalid token practiceId", undefined, { + throw new MetriportError(`Token practice ID mismatch, expected ${practiceId}`, undefined, { tokenId, source: token.data.source, tokenPracticeId, practiceId, + expectedPracticeId: practiceId, }); }packages/core/src/external/ehr/eclinicalworks/index.ts (1)
28-33
: Improve URL construction clarity.The conditional URL construction for environment could be clearer and more maintainable.
+ private getBaseUrl(environment: EClinicalWorksEnv): string { + const subdomain = environment === "production" ? "" : "staging-"; + return `https://${subdomain}fhir.ecwcloud.com`; + } + private constructor(config: EClinicalWorksApiConfig) { this.practiceId = config.practiceId; - this.baseFhirUrl = `https://${ - config.environment === "production" ? "" : "staging-" - }fhir.ecwcloud.com`; + this.baseFhirUrl = this.getBaseUrl(config.environment); this.axiosFhirInstance = axios.create({}); this.token = config.authToken; }packages/core/src/external/fhir/export/string/shared/dosage.ts (1)
40-46
: Prefer optional-chaining over boolean short-circuit forjoin
doseAndRateStr && doseAndRateStr.join(...)
works, but optional-chaining conveys the intent more clearly, avoids accidental coercion, and is exactly what the linter is hinting at.- doseAndRateStr && doseAndRateStr.join(FIELD_SEPARATOR), + doseAndRateStr?.join(FIELD_SEPARATOR),🧰 Tools
🪛 Biome (1.9.4)
[error] 45-45: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
packages/core/src/external/fhir/export/string/resources/medication-request.ts (1)
22-24
: Add a debug label for identifiers to keep output self-describingWhen
isDebug
is enabled the rest of the fields are nicely prefixed (e.g., “Status: …”). Identifiers are currently pushed raw, breaking the consistency of the debug output.- const identifierStr = formatIdentifiers({ identifiers: request.identifier }); - if (identifierStr) parts.push(identifierStr); + const identifierStr = formatIdentifiers({ identifiers: request.identifier }); + if (identifierStr) { + parts.push(isDebug ? `Identifier: ${identifierStr}` : identifierStr); + }packages/core/src/command/consolidated/consolidated-get.ts (2)
98-112
: Consider surfacing connector errors instead of silently returning rejected promises
getConsolidatedPatientData
awaits the connector call and will bubble-up any error (👍), butgetConsolidatedPatientDataAsync
deliberately fires-and-forgets by returningvoid
and handling errors only throughprocessAsyncError
.
If a caller expects to await resolution (e.g., in a background job chain) it will never know that the execution finished/failed.Two lightweight approaches:
- connector - .execute(payload) - .catch(processAsyncError("Failed to get consolidated patient data async", undefined, true)); + // Return the promise so callers can await *if* they want, while still attaching + // the default error-handler when it is not awaited. + return connector + .execute(payload) + .catch(processAsyncError("Failed to get consolidated patient data async", undefined, true));or keep the current signature but document clearly that the promise is not settled.
Either way, make the contract explicit so downstream code is not surprised.
150-157
: Guard against empty bundles before converting to textIf
getConsolidatedPatientData
eventually returnsundefined
(e.g., S3 key not found)bundleToString
will throw.
A minimal defensive check keeps the helper 100 % safe:- const consolidated = await getConsolidatedPatientData({ patient }); - return bundleToString(consolidated); + const consolidated = await getConsolidatedPatientData({ patient }); + if (!consolidated) return []; + return bundleToString(consolidated);packages/core/src/external/opensearch/text-ingestor.ts (2)
144-156
: Chunk ingestion could overshoot the 5-15 MB guidelineThe fixed
bulkChunkSize = 500
assumes an average 10 KB resource; larger notes/images will blow past the recommended bulk payload, increasing the chance of 413/504 errors.Consider building chunks based on total serialized size instead of fixed item count (the TODO already hints at this). A quick heuristic:
// pseudo-code let currentBatch: IngestRequestResource[] = []; let currentSize = 0; for (const r of resources) { const size = Buffer.byteLength(JSON.stringify(r.content), 'utf8'); if (currentSize + size > MAX_BATCH_BYTES) flushBatch(); currentBatch.push(r); currentSize += size; }This keeps requests within OpenSearch limits and avoids unpredictable failures.
234-239
: Minor typo – ‘requeests’- * NOTE: Assumes all requeests are for the same index and operation! + * NOTE: Assumes all requests are for the same index and operation!
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (144)
packages/api/src/command/hie/unlink-patient-from-organization.ts
(1 hunks)packages/api/src/command/jwt-token.ts
(2 hunks)packages/api/src/command/medical/patient/consolidated-delete.ts
(1 hunks)packages/api/src/command/medical/patient/consolidated-get.ts
(1 hunks)packages/api/src/errors/index.ts
(1 hunks)packages/api/src/external/carequality/document/process-outbound-document-retrieval-resps.ts
(2 hunks)packages/api/src/external/cda/generate-ccd.ts
(2 hunks)packages/api/src/external/commonwell/document/document-query.ts
(2 hunks)packages/api/src/external/ehr/eclinicalworks/command/sync-patient.ts
(1 hunks)packages/api/src/external/ehr/eclinicalworks/shared.ts
(1 hunks)packages/api/src/external/ehr/shared/utils/bundle/functions.ts
(1 hunks)packages/api/src/external/ehr/shared/utils/client.ts
(3 hunks)packages/api/src/external/ehr/shared/utils/jwt-token.ts
(3 hunks)packages/api/src/external/ehr/shared/utils/mappings.ts
(1 hunks)packages/api/src/external/opensearch/file-search-connector-factory.ts
(0 hunks)packages/api/src/routes/ehr/eclinicalworks/auth/middleware.ts
(1 hunks)packages/api/src/routes/ehr/eclinicalworks/patient.ts
(1 hunks)packages/api/src/routes/ehr/eclinicalworks/routes/dash.ts
(1 hunks)packages/api/src/routes/ehr/index.ts
(2 hunks)packages/api/src/routes/ehr/shared.ts
(1 hunks)packages/api/src/routes/internal/jwt-token/eclinicalworks.ts
(1 hunks)packages/api/src/routes/internal/jwt-token/index.ts
(2 hunks)packages/api/src/routes/internal/medical/patient-consolidated.ts
(1 hunks)packages/api/src/routes/internal/medical/patient.ts
(4 hunks)packages/api/src/routes/medical/document.ts
(1 hunks)packages/api/src/routes/medical/patient.ts
(3 hunks)packages/api/src/shared/config.ts
(1 hunks)packages/core/src/command/ai-brief/filter.ts
(7 hunks)packages/core/src/command/consolidated/consolidated-filter.ts
(5 hunks)packages/core/src/command/consolidated/consolidated-get.ts
(3 hunks)packages/core/src/command/consolidated/get-snapshot.ts
(1 hunks)packages/core/src/command/consolidated/search/document-reference/ingest.ts
(1 hunks)packages/core/src/command/consolidated/search/document-reference/search.ts
(2 hunks)packages/core/src/command/consolidated/search/fhir-resource/ingest-lexical.ts
(1 hunks)packages/core/src/command/consolidated/search/fhir-resource/ingest-semantic.ts
(1 hunks)packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-direct.ts
(1 hunks)packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-factory.ts
(1 hunks)packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts
(1 hunks)packages/core/src/command/consolidated/search/fhir-resource/search-lexical.ts
(1 hunks)packages/core/src/command/consolidated/search/fhir-resource/search-semantic.ts
(5 hunks)packages/core/src/command/consolidated/snapshot-on-s3.ts
(1 hunks)packages/core/src/domain/ai-brief/modify-resources.ts
(2 hunks)packages/core/src/external/aws/document-signing/bulk-sign.ts
(1 hunks)packages/core/src/external/ehr/bundle/job/create-resource-diff-bundles/steps/compute/ehr-compute-resource-diff-bundles-local.ts
(2 hunks)packages/core/src/external/ehr/eclinicalworks/index.ts
(1 hunks)packages/core/src/external/fhir/__tests__/bundle.ts
(1 hunks)packages/core/src/external/fhir/codeable-concept.ts
(1 hunks)packages/core/src/external/fhir/consolidated/consolidated.ts
(1 hunks)packages/core/src/external/fhir/export/string/bundle-to-string.ts
(6 hunks)packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/allergy-intolerance.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/communication.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/composition.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/condition.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/consent.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/coverage.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/diagnostic-report.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/document-reference.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/encounter.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/family-member-history.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/immunization.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/location.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/medication-administration.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/medication-dispense.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/medication-request.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/medication-statement.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/medication.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/observation.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/organization.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/patient.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/practitioner.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/procedure.ts
(1 hunks)packages/core/src/external/fhir/export/string/resources/related-person.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/__tests__/codeable-concept.test.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/__tests__/timing.test.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/address.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/age.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/annotation.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/attachment.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/code-display.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/codeable-concept.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/coding.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/debug.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/deny.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/dosage.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/duration.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/human-name.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/identifier.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/narrative.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/numeric.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/period.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/quantity.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/range.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/ratio.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/reference.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/string.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/telecom.ts
(1 hunks)packages/core/src/external/fhir/export/string/shared/timing.ts
(1 hunks)packages/core/src/external/fhir/normalization/resources/encounter.ts
(1 hunks)packages/core/src/external/fhir/resources/diagnostic-report.ts
(1 hunks)packages/core/src/external/html/remove-tags.ts
(1 hunks)packages/core/src/external/opensearch/cda.ts
(0 hunks)packages/core/src/external/opensearch/file-searcher.ts
(0 hunks)packages/core/src/external/opensearch/file/file-ingestor-direct.ts
(3 hunks)packages/core/src/external/opensearch/file/file-ingestor-sqs.ts
(1 hunks)packages/core/src/external/opensearch/file/file-ingestor.ts
(1 hunks)packages/core/src/external/opensearch/file/file-remover-direct.ts
(1 hunks)packages/core/src/external/opensearch/file/file-search-connector-factory.ts
(3 hunks)packages/core/src/external/opensearch/file/file-searcher-direct.ts
(2 hunks)packages/core/src/external/opensearch/file/file-searcher.ts
(1 hunks)packages/core/src/external/opensearch/index-based-on-file.ts
(1 hunks)packages/core/src/external/opensearch/index-based-on-resource.ts
(1 hunks)packages/core/src/external/opensearch/index.ts
(1 hunks)packages/core/src/external/opensearch/lexical/lexical-search.ts
(1 hunks)packages/core/src/external/opensearch/lexical/lexical-searcher.ts
(1 hunks)packages/core/src/external/opensearch/semantic/hybrid-create.ts
(1 hunks)packages/core/src/external/opensearch/semantic/ingest.ts
(0 hunks)packages/core/src/external/opensearch/semantic/semantic-searcher.ts
(5 hunks)packages/core/src/external/opensearch/semantic/shared.ts
(0 hunks)packages/core/src/external/opensearch/shared/bulk.ts
(1 hunks)packages/core/src/external/opensearch/shared/delete.ts
(1 hunks)packages/core/src/external/opensearch/shared/filters.ts
(1 hunks)packages/core/src/external/opensearch/shared/id.ts
(1 hunks)packages/core/src/external/opensearch/shared/log.ts
(1 hunks)packages/core/src/external/opensearch/text-ingestor-direct.ts
(0 hunks)packages/core/src/external/opensearch/text-ingestor.ts
(1 hunks)packages/core/src/util/config.ts
(1 hunks)packages/core/src/util/error/shared.ts
(1 hunks)packages/infra/config/env-config.ts
(1 hunks)packages/infra/lib/api-stack.ts
(1 hunks)packages/infra/lib/api-stack/api-service.ts
(2 hunks)packages/infra/lib/api-stack/ccda-search-connector.ts
(1 hunks)packages/lambdas/src/shared/ehr.ts
(1 hunks)packages/lambdas/src/sqs-to-opensearch-xml.ts
(2 hunks)packages/shared/src/interface/external/ehr/eclinicalworks/index.ts
(1 hunks)packages/shared/src/interface/external/ehr/eclinicalworks/jwt-token.ts
(1 hunks)packages/shared/src/interface/external/ehr/source.ts
(1 hunks)packages/utils/src/fhir/ai-brief/build-slim-bundle.ts
(1 hunks)packages/utils/src/open-search/cleanup.ts
(1 hunks)packages/utils/src/open-search/re-populate.ts
(1 hunks)packages/utils/src/open-search/semantic-ingest.ts
(2 hunks)packages/utils/src/open-search/semantic-search.ts
(1 hunks)packages/utils/src/open-search/semantic-text-from-consolidated.ts
(2 hunks)packages/utils/src/shared/sentry.ts
(1 hunks)
💤 Files with no reviewable changes (6)
- packages/core/src/external/opensearch/semantic/shared.ts
- packages/api/src/external/opensearch/file-search-connector-factory.ts
- packages/core/src/external/opensearch/cda.ts
- packages/core/src/external/opensearch/file-searcher.ts
- packages/core/src/external/opensearch/text-ingestor-direct.ts
- packages/core/src/external/opensearch/semantic/ingest.ts
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.ts`: - Use the Onion Pattern to organize a package's code in layers - Try to use immutable code and avoid sharing state across different functions, objects, and systems - Try...
**/*.ts
: - Use the Onion Pattern to organize a package's code in layers
- Try to use immutable code and avoid sharing state across different functions, objects, and systems
- Try to build code that's idempotent whenever possible
- Prefer functional programming style functions: small, deterministic, 1 input, 1 output
- Minimize coupling / dependencies
- Avoid modifying objects received as parameter
- Only add comments to code to explain why something was done, not how it works
- Naming
- classes, enums:
PascalCase
- constants, variables, functions:
camelCase
- file names:
kebab-case
- table and column names:
snake_case
- Use meaningful names, so whoever is reading the code understands what it means
- Don’t use negative names, like
notEnabled
, 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 d 10000 efault 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
packages/core/src/external/opensearch/file/file-remover-direct.ts
packages/core/src/external/fhir/normalization/resources/encounter.ts
packages/utils/src/open-search/cleanup.ts
packages/core/src/external/fhir/export/string/shared/debug.ts
packages/api/src/routes/internal/jwt-token/index.ts
packages/core/src/external/ehr/bundle/job/create-resource-diff-bundles/steps/compute/ehr-compute-resource-diff-bundles-local.ts
packages/utils/src/open-search/semantic-search.ts
packages/core/src/external/opensearch/file/file-ingestor-sqs.ts
packages/lambdas/src/sqs-to-opensearch-xml.ts
packages/api/src/external/ehr/shared/utils/bundle/functions.ts
packages/lambdas/src/shared/ehr.ts
packages/utils/src/open-search/re-populate.ts
packages/shared/src/interface/external/ehr/eclinicalworks/index.ts
packages/core/src/external/opensearch/file/file-search-connector-factory.ts
packages/api/src/routes/medical/document.ts
packages/shared/src/interface/external/ehr/source.ts
packages/api/src/errors/index.ts
packages/api/src/external/ehr/shared/utils/mappings.ts
packages/core/src/command/consolidated/snapshot-on-s3.ts
packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-factory.ts
packages/api/src/command/medical/patient/consolidated-delete.ts
packages/core/src/external/fhir/export/string/shared/code-display.ts
packages/infra/lib/api-stack/ccda-search-connector.ts
packages/infra/lib/api-stack.ts
packages/core/src/util/config.ts
packages/core/src/external/opensearch/shared/id.ts
packages/core/src/domain/ai-brief/modify-resources.ts
packages/utils/src/shared/sentry.ts
packages/api/src/routes/ehr/index.ts
packages/core/src/external/fhir/codeable-concept.ts
packages/core/src/external/fhir/__tests__/bundle.ts
packages/api/src/external/ehr/eclinicalworks/shared.ts
packages/core/src/external/fhir/export/string/shared/string.ts
packages/core/src/command/consolidated/get-snapshot.ts
packages/core/src/external/opensearch/shared/filters.ts
packages/infra/lib/api-stack/api-service.ts
packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts
packages/infra/config/env-config.ts
packages/core/src/external/fhir/export/string/shared/__tests__/timing.test.ts
packages/api/src/external/commonwell/document/document-query.ts
packages/core/src/external/opensearch/semantic/hybrid-create.ts
packages/api/src/shared/config.ts
packages/core/src/external/fhir/export/string/shared/age.ts
packages/core/src/command/consolidated/consolidated-filter.ts
packages/api/src/command/hie/unlink-patient-from-organization.ts
packages/core/src/external/opensearch/index-based-on-resource.ts
packages/core/src/external/fhir/export/string/shared/range.ts
packages/api/src/routes/ehr/eclinicalworks/patient.ts
packages/api/src/command/jwt-token.ts
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts
packages/core/src/external/opensearch/shared/delete.ts
packages/shared/src/interface/external/ehr/eclinicalworks/jwt-token.ts
packages/api/src/external/ehr/shared/utils/jwt-token.ts
packages/core/src/external/fhir/export/string/shared/narrative.ts
packages/core/src/external/fhir/export/string/resources/medication.ts
packages/api/src/routes/ehr/eclinicalworks/routes/dash.ts
packages/core/src/external/fhir/export/string/resources/communication.ts
packages/api/src/command/medical/patient/consolidated-get.ts
packages/core/src/external/opensearch/shared/log.ts
packages/core/src/util/error/shared.ts
packages/core/src/external/fhir/export/string/resources/coverage.ts
packages/utils/src/open-search/semantic-text-from-consolidated.ts
packages/core/src/external/fhir/export/string/resources/procedure.ts
packages/core/src/external/aws/document-signing/bulk-sign.ts
packages/core/src/external/fhir/export/string/resources/patient.ts
packages/core/src/external/fhir/export/string/shared/ratio.ts
packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-direct.ts
packages/core/src/external/fhir/export/string/resources/related-person.ts
packages/core/src/command/consolidated/search/fhir-resource/search-lexical.ts
packages/core/src/external/fhir/export/string/resources/practitioner.ts
packages/core/src/external/fhir/export/string/shared/reference.ts
packages/api/src/routes/internal/jwt-token/eclinicalworks.ts
packages/core/src/external/fhir/export/string/resources/medication-administration.ts
packages/core/src/external/opensearch/lexical/lexical-search.ts
packages/core/src/external/fhir/export/string/shared/quantity.ts
packages/core/src/external/fhir/export/string/shared/period.ts
packages/api/src/routes/ehr/shared.ts
packages/core/src/command/consolidated/search/fhir-resource/ingest-semantic.ts
packages/core/src/external/fhir/export/string/resources/medication-statement.ts
packages/core/src/external/opensearch/semantic/semantic-searcher.ts
packages/utils/src/fhir/ai-brief/build-slim-bundle.ts
packages/core/src/external/opensearch/file/file-ingestor.ts
packages/core/src/external/opensearch/file/file-ingestor-direct.ts
packages/core/src/command/consolidated/search/document-reference/ingest.ts
packages/core/src/external/fhir/export/string/resources/composition.ts
packages/core/src/external/fhir/resources/diagnostic-report.ts
packages/core/src/external/fhir/export/string/bundle-to-string.ts
packages/core/src/external/fhir/export/string/resources/encounter.ts
packages/core/src/external/opensearch/lexical/lexical-searcher.ts
packages/core/src/external/fhir/export/string/resources/consent.ts
packages/core/src/command/consolidated/search/fhir-resource/search-semantic.ts
packages/api/src/external/cda/generate-ccd.ts
packages/core/src/external/fhir/export/string/resources/family-member-history.ts
packages/core/src/external/fhir/export/string/resources/immunization.ts
packages/core/src/external/fhir/export/string/resources/medication-dispense.ts
packages/api/src/routes/internal/medical/patient.ts
packages/core/src/external/html/remove-tags.ts
packages/api/src/external/ehr/shared/utils/client.ts
packages/core/src/external/opensearch/file/file-searcher.ts
packages/core/src/external/fhir/export/string/resources/observation.ts
packages/core/src/external/fhir/export/string/resources/document-reference.ts
packages/api/src/routes/medical/patient.ts
packages/api/src/external/carequality/document/process-outbound-document-retrieval-resps.ts
packages/core/src/external/fhir/export/string/shared/duration.ts
packages/core/src/external/fhir/consolidated/consolidated.ts
packages/core/src/command/consolidated/search/document-reference/search.ts
packages/core/src/external/fhir/export/string/shared/annotation.ts
packages/core/src/external/fhir/export/string/resources/condition.ts
packages/core/src/external/fhir/export/string/resources/location.ts
packages/core/src/external/opensearch/file/file-searcher-direct.ts
packages/core/src/external/fhir/export/string/shared/attachment.ts
packages/core/src/external/fhir/export/string/shared/numeric.ts
packages/core/src/external/fhir/export/string/shared/identifier.ts
packages/core/src/external/fhir/export/string/shared/human-name.ts
packages/api/src/external/ehr/eclinicalworks/command/sync-patient.ts
packages/core/src/external/opensearch/shared/bulk.ts
packages/core/src/external/fhir/export/string/shared/deny.ts
packages/core/src/external/fhir/export/string/resources/diagnostic-report.ts
packages/core/src/external/fhir/export/string/resources/allergy-intolerance.ts
packages/core/src/external/fhir/export/string/resources/organization.ts
packages/core/src/external/fhir/export/string/shared/address.ts
packages/utils/src/open-search/semantic-ingest.ts
packages/api/src/routes/ehr/eclinicalworks/auth/middleware.ts
packages/core/src/command/consolidated/search/fhir-resource/ingest-lexical.ts
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts
packages/core/src/external/fhir/export/string/shared/__tests__/codeable-concept.test.ts
packages/api/src/routes/internal/medical/patient-consolidated.ts
packages/core/src/external/ehr/eclinicalworks/index.ts
packages/core/src/external/fhir/export/string/resources/medication-request.ts
packages/core/src/external/fhir/export/string/shared/dosage.ts
packages/core/src/external/fhir/export/string/shared/coding.ts
packages/core/src/command/consolidated/consolidated-get.ts
packages/core/src/external/fhir/export/string/shared/timing.ts
packages/core/src/external/fhir/export/string/shared/telecom.ts
packages/core/src/command/ai-brief/filter.ts
packages/core/src/external/opensearch/index.ts
packages/core/src/external/opensearch/index-based-on-file.ts
packages/core/src/external/opensearch/text-ingestor.ts
🧠 Learnings (8)
packages/api/src/command/medical/patient/consolidated-delete.ts (1)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/api/src/routes/internal/medical/patient-consolidated.ts:141-174
Timestamp: 2025-05-20T21:26:26.804Z
Learning: The functionality introduced in packages/api/src/routes/internal/medical/patient-consolidated.ts is planned to be refactored in downstream PR #3857, including improvements to error handling and validation.
packages/api/src/routes/ehr/eclinicalworks/patient.ts (1)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/api/src/routes/internal/medical/patient-consolidated.ts:141-174
Timestamp: 2025-05-20T21:26:26.804Z
Learning: The functionality introduced in packages/api/src/routes/internal/medical/patient-consolidated.ts is planned to be refactored in downstream PR #3857, including improvements to error handling and validation.
packages/api/src/command/medical/patient/consolidated-get.ts (2)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/api/src/routes/internal/medical/patient-consolidated.ts:141-174
Timestamp: 2025-05-20T21:26:26.804Z
Learning: The functionality introduced in packages/api/src/routes/internal/medical/patient-consolidated.ts is planned to be refactored in downstream PR #3857, including improvements to error handling and validation.
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/core/src/command/consolidated/search/fhir-resource/search-semantic.ts:36-36
Timestamp: 2025-05-19T13:53:09.828Z
Learning: In the `getConsolidatedPatientData` function from `@metriport/core/command/consolidated/consolidated-get`, only the `patient` parameter is required. Other parameters like `requestId`, `resources`, `dateFrom`, `dateTo`, `fromDashboard`, and `forceDataFromFhir` are all optional.
packages/api/src/routes/internal/medical/patient.ts (1)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/api/src/routes/internal/medical/patient-consolidated.ts:141-174
Timestamp: 2025-05-20T21:26:26.804Z
Learning: The functionality introduced in packages/api/src/routes/internal/medical/patient-consolidated.ts is planned to be refactored in downstream PR #3857, including improvements to error handling and validation.
packages/core/src/external/html/remove-tags.ts (2)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/core/src/external/opensearch/file/file-ingestor-direct.ts:91-100
Timestamp: 2025-05-19T14:09:12.444Z
Learning: In packages/core/src/external/html/remove-tags.ts, the `removeHtmlTags` function has an `isRemoveNewLinesAndSpaces` parameter that defaults to true, which automatically handles the removal of newlines, tabs, carriage returns, and multiple spaces without needing to explicitly set this parameter when calling the function.
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/core/src/external/opensearch/file/file-ingestor-direct.ts:91-100
Timestamp: 2025-05-19T14:09:12.444Z
Learning: In packages/core/src/external/html/remove-tags.ts, the `removeHtmlTags` function has an `isRemoveNewLinesAndSpaces` parameter that defaults to true, which automatically handles the removal of newlines, tabs, carriage returns, and multiple spaces without needing to explicitly set this parameter when calling the function.
packages/api/src/routes/medical/patient.ts (1)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/api/src/routes/internal/medical/patient-consolidated.ts:141-174
Timestamp: 2025-05-20T21:26:26.804Z
Learning: The functionality introduced in packages/api/src/routes/internal/medical/patient-consolidated.ts is planned to be refactored in downstream PR #3857, including improvements to error handling and validation.
packages/api/src/routes/internal/medical/patient-consolidated.ts (1)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/api/src/routes/internal/medical/patient-consolidated.ts:141-174
Timestamp: 2025-05-20T21:26:26.804Z
Learning: The functionality introduced in packages/api/src/routes/internal/medical/patient-consolidated.ts is planned to be refactored in downstream PR #3857, including improvements to error handling and validation.
packages/core/src/command/consolidated/consolidated-get.ts (2)
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/api/src/routes/internal/medical/patient-consolidated.ts:141-174
Timestamp: 2025-05-20T21:26:26.804Z
Learning: The functionality introduced in packages/api/src/routes/internal/medical/patient-consolidated.ts is planned to be refactored in downstream PR #3857, including improvements to error handling and validation.
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/core/src/command/consolidated/search/fhir-resource/search-semantic.ts:36-36
Timestamp: 2025-05-19T13:53:09.828Z
Learning: In the `getConsolidatedPatientData` function from `@metriport/core/command/consolidated/consolidated-get`, only the `patient` parameter is required. Other parameters like `requestId`, `resources`, `dateFrom`, `dateTo`, `fromDashboard`, and `forceDataFromFhir` are all optional.
🧬 Code Graph Analysis (65)
packages/core/src/external/ehr/bundle/job/create-resource-diff-bundles/steps/compute/ehr-compute-resource-diff-bundles-local.ts (1)
packages/core/src/command/consolidated/consolidated-get.ts (1)
getConsolidatedFile
(43-61)
packages/core/src/external/opensearch/file/file-search-connector-factory.ts (1)
packages/core/src/util/config.ts (1)
Config
(9-226)
packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-factory.ts (2)
packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts (1)
SearchConsolidated
(13-15)packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-direct.ts (1)
SearchConsolidatedDirect
(31-48)
packages/core/src/external/fhir/export/string/shared/code-display.ts (1)
packages/core/src/external/fhir/codeable-concept.ts (1)
isUsefulDisplay
(44-51)
packages/api/src/external/ehr/eclinicalworks/shared.ts (3)
packages/api/src/shared/config.ts (1)
getEClinicalWorksEnv
(335-337)packages/core/src/external/ehr/eclinicalworks/index.ts (2)
EClinicalWorksEnv
(15-15)isEClinicalWorksEnv
(16-18)packages/api/src/external/ehr/shared/utils/client.ts (1)
EhrPerPracticeParams
(31-31)
packages/core/src/external/fhir/export/string/shared/string.ts (1)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/core/src/external/fhir/export/string/shared/age.ts (1)
packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
formatQuantity
(11-24)
packages/core/src/command/consolidated/consolidated-filter.ts (3)
packages/core/src/command/consolidated/consolidated-get.ts (1)
getConsolidatedFile
(43-61)packages/shared/src/common/date.ts (1)
elapsedTimeFromNow
(63-68)packages/core/src/external/fhir/shared/bundle.ts (1)
buildBundleEntry
(187-193)
packages/core/src/external/opensearch/index-based-on-resource.ts (2)
packages/core/src/external/opensearch/index-based-on-file.ts (2)
IndexFields
(3-8)SearchResult
(10-12)packages/core/src/external/opensearch/index.ts (1)
contentFieldName
(1-1)
packages/core/src/external/fhir/export/string/shared/range.ts (3)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
defaultIsDebug
(1-1)packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
formatQuantity
(11-24)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/api/src/command/jwt-token.ts (2)
packages/api/src/domain/jwt-token.ts (1)
JwtToken
(30-30)packages/shared/src/index.ts (1)
NotFoundError
(41-41)
packages/core/src/external/opensearch/shared/delete.ts (1)
packages/core/src/external/opensearch/shared/filters.ts (1)
getPatientFilters
(1-3)
packages/api/src/external/ehr/shared/utils/jwt-token.ts (2)
packages/shared/src/interface/external/ehr/eclinicalworks/jwt-token.ts (2)
eclinicalworksDashSource
(4-4)EClinicalWorksDashJwtTokenData
(10-10)packages/shared/src/interface/external/ehr/healthie/jwt-token.ts (1)
HealthieDashJwtTokenData
(10-10)
packages/core/src/external/fhir/export/string/shared/narrative.ts (2)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
defaultIsDebug
(1-1)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/core/src/external/fhir/export/string/resources/medication.ts (6)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (1)
FHIRResourceToString
(8-16)packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
formatIdentifiers
(5-19)packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)
formatCodeableConcepts
(78-96)formatCodeableConcept
(18-68)packages/core/src/external/fhir/export/string/shared/reference.ts (1)
formatReferences
(8-26)packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
formatQuantity
(11-24)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/api/src/routes/ehr/eclinicalworks/routes/dash.ts (2)
packages/api/src/routes/ehr/shared.ts (4)
documentDownloadUrlRegex
(48-48)processPatientRoute
(91-100)processEhrPatientId
(135-154)processDocumentRoute
(102-111)packages/api/src/routes/ehr/eclinicalworks/auth/middleware.ts (3)
processPatientRoute
(39-41)tokenEhrPatientIdQueryParam
(12-12)processDocumentRoute
(43-45)
packages/core/src/external/opensearch/shared/log.ts (1)
packages/shared/src/index.ts (1)
emptyFunction
(7-7)
packages/core/src/util/error/shared.ts (3)
packages/api/src/errors/index.ts (2)
processAsyncError
(13-20)getErrorMessage
(6-8)packages/shared/src/index.ts (2)
BadRequestError
(39-39)NotFoundError
(41-41)packages/lambdas/src/shared/capture.ts (1)
capture
(18-103)
packages/utils/src/open-search/semantic-text-from-consolidated.ts (5)
packages/shared/src/index.ts (1)
sleep
(13-13)packages/core/src/external/fhir/export/string/bundle-to-string.ts (2)
FhirResourceToText
(116-120)bundleToString
(131-145)packages/api-sdk/src/medical/client/metriport.ts (1)
MetriportMedicalApi
(85-902)packages/core/src/command/patient-loader-metriport-api.ts (1)
getDomainFromDTO
(112-141)packages/core/src/command/consolidated/consolidated-get.ts (1)
getConsolidatedAsText
(150-157)
packages/core/src/external/fhir/export/string/resources/patient.ts (4)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (1)
FHIRResourceToString
(8-16)packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
formatIdentifiers
(5-19)packages/core/src/external/fhir/export/string/shared/human-name.ts (1)
formatHumanNames
(14-31)packages/core/src/external/fhir/export/string/shared/address.ts (1)
formatAddresses
(11-27)
packages/core/src/external/fhir/export/string/shared/ratio.ts (3)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
defaultIsDebug
(1-1)packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
formatQuantity
(11-24)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/core/src/external/fhir/export/string/resources/related-person.ts (7)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
FHIRResourceToString
(8-16)defaultHasMinimumData
(3-3)packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
formatIdentifiers
(5-19)packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
formatCodeableConcepts
(78-96)packages/core/src/external/fhir/export/string/shared/human-name.ts (1)
formatHumanNames
(14-31)packages/core/src/external/fhir/export/string/shared/telecom.ts (1)
formatTelecoms
(12-27)packages/core/src/external/fhir/export/string/shared/address.ts (1)
formatAddresses
(11-27)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/core/src/external/fhir/export/string/resources/practitioner.ts (7)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (1)
FHIRResourceToString
(8-16)packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
formatNpiIdentifiers
(52-58)packages/core/src/external/fhir/export/string/shared/human-name.ts (1)
formatHumanNames
(14-31)packages/core/src/external/fhir/export/string/shared/telecom.ts (1)
formatTelecoms
(12-27)packages/core/src/external/fhir/export/string/shared/address.ts (1)
formatAddresses
(11-27)packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
formatCodeableConcept
(18-68)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/core/src/external/fhir/export/string/shared/reference.ts (2)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
defaultIsDebug
(1-1)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/api/src/routes/internal/jwt-token/eclinicalworks.ts (2)
packages/api/src/external/ehr/shared/utils/jwt-token.ts (2)
checkJwtToken
(74-88)saveJwtToken
(90-107)packages/shared/src/interface/external/ehr/eclinicalworks/jwt-token.ts (2)
eclinicalworksDashSource
(4-4)eclinicalworksDashJwtTokenDataSchema
(5-9)
packages/core/src/external/opensearch/lexical/lexical-search.ts (2)
packages/core/src/external/opensearch/index.ts (1)
contentFieldName
(1-1)packages/core/src/external/opensearch/shared/filters.ts (1)
getPatientFilters
(1-3)
packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
defaultIsDebug
(1-1)
packages/core/src/external/fhir/export/string/shared/period.ts (2)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
defaultIsDebug
(1-1)packages/core/src/domain/patient.ts (1)
Period
(18-26)
packages/api/src/routes/ehr/shared.ts (3)
packages/api/src/domain/jwt-token.ts (1)
JwtTokenData
(21-21)packages/api/src/command/jwt-token.ts (1)
getJwtToken
(26-35)packages/shared/src/common/date.ts (1)
buildDayjs
(70-72)
packages/core/src/command/consolidated/search/fhir-resource/ingest-semantic.ts (3)
packages/core/src/external/opensearch/shared/bulk.ts (1)
OnBulkItemError
(25-25)packages/core/src/command/consolidated/consolidated-get.ts (1)
getConsolidatedAsText
(150-157)packages/core/src/external/opensearch/text-ingestor.ts (2)
OpenSearchTextIngestor
(59-224)convertFhirResourceToTextToIngestRequestResource
(241-249)
packages/core/src/external/opensearch/semantic/semantic-searcher.ts (1)
packages/core/src/external/opensearch/index.ts (3)
OpenSearchConfigDirectAccess
(7-11)OpenSearchResponse
(21-25)OpenSearchResponseHit
(14-19)
packages/core/src/external/opensearch/file/file-ingestor.ts (2)
packages/core/src/external/opensearch/index.ts (1)
OpenSearchConfig
(3-6)packages/infra/config/example.ts (1)
config
(8-228)
packages/core/src/external/opensearch/file/file-ingestor-direct.ts (1)
packages/core/src/external/html/remove-tags.ts (1)
removeHtmlTags
(41-91)
packages/core/src/command/consolidated/search/document-reference/ingest.ts (1)
packages/core/src/external/opensearch/file/file-search-connector-factory.ts (1)
makeSearchServiceIngest
(10-30)
packages/core/src/external/fhir/export/string/bundle-to-string.ts (7)
packages/core/src/external/fhir/export/string/resources/consent.ts (1)
ConsentToString
(20-220)packages/core/src/external/fhir/export/string/resources/composition.ts (1)
CompositionToString
(13-136)packages/core/src/external/fhir/export/string/resources/communication.ts (1)
CommunicationToString
(12-117)packages/core/src/external/fhir/export/string/resources/coverage.ts (1)
CoverageToString
(14-143)packages/core/src/external/fhir/export/string/resources/document-reference.ts (1)
DocumentReferenceToString
(13-162)packages/core/src/external/fhir/export/string/resources/related-person.ts (1)
RelatedPersonToString
(13-92)packages/core/src/external/fhir/export/string/resources/patient.ts (1)
PatientToString
(11-30)
packages/core/src/external/fhir/export/string/resources/encounter.ts (5)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
FHIRResourceToString
(8-16)defaultHasMinimumData
(3-3)packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
formatIdentifiers
(5-19)packages/core/src/external/fhir/export/string/shared/deny.ts (1)
emptyIfDenied
(9-15)packages/core/src/external/fhir/export/string/shared/coding.ts (1)
formatCoding
(42-65)packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
formatCodeableConcepts
(78-96)
packages/core/src/external/fhir/export/string/resources/family-member-history.ts (6)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
FHIRResourceToString
(8-16)defaultHasMinimumData
(3-3)packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)
formatCodeableConcepts
(78-96)formatCodeableConcept
(18-68)packages/core/src/external/fhir/export/string/shared/period.ts (1)
formatPeriod
(11-25)packages/core/src/external/fhir/export/string/shared/annotation.ts (1)
formatAnnotations
(5-21)packages/core/src/external/fhir/export/string/shared/age.ts (1)
formatAge
(8-18)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/core/src/external/fhir/export/string/resources/medication-dispense.ts (6)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
FHIRResourceToString
(8-16)defaultHasMinimumData
(3-3)packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
formatIdentifiers
(5-19)packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
formatCodeableConcept
(18-68)packages/core/src/external/fhir/export/string/shared/reference.ts (2)
formatReference
(28-41)formatReferences
(8-26)packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
formatQuantity
(11-24)packages/core/src/external/fhir/export/string/shared/annotation.ts (1)
formatAnnotations
(5-21)
packages/api/src/external/ehr/shared/utils/client.ts (5)
packages/core/src/external/ehr/athenahealth/index.ts (1)
AthenaEnv
(93-93)packages/core/src/external/ehr/elation/index.ts (1)
ElationEnv
(54-54)packages/core/src/external/ehr/canvas/index.ts (1)
CanvasEnv
(75-75)packages/core/src/external/ehr/healthie/index.ts (1)
HealthieEnv
(40-40)packages/core/src/external/ehr/eclinicalworks/index.ts (1)
EClinicalWorksEnv
(15-15)
packages/core/src/external/fhir/export/string/resources/observation.ts (6)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (1)
FHIRResourceToString
(8-16)packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
formatIdentifiers
(5-19)packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)
formatCodeableConcepts
(78-96)formatCodeableConcept
(18-68)packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
formatQuantity
(11-24)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)packages/core/src/external/fhir/export/string/shared/reference.ts (1)
formatReferences
(8-26)
packages/api/src/routes/medical/patient.ts (1)
packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-factory.ts (1)
makeSearchConsolidated
(5-11)
packages/api/src/external/carequality/document/process-outbound-document-retrieval-resps.ts (1)
packages/core/src/command/consolidated/search/document-reference/ingest.ts (1)
ingestIntoSearchEngine
(7-49)
packages/core/src/external/fhir/export/string/shared/duration.ts (1)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
defaultIsDebug
(1-1)
packages/core/src/external/fhir/export/string/shared/annotation.ts (2)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
defaultIsDebug
(1-1)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/core/src/external/fhir/export/string/resources/condition.ts (10)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
FHIRResourceToString
(8-16)defaultHasMinimumData
(3-3)packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
formatIdentifiers
(5-19)packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)
formatCodeableConcept
(18-68)formatCodeableConcepts
(78-96)packages/core/src/external/fhir/export/string/shared/reference.ts (2)
formatReference
(28-41)formatReferences
(8-26)packages/core/src/external/fhir/export/string/shared/age.ts (1)
formatAge
(8-18)packages/core/src/external/fhir/export/string/shared/period.ts (1)
formatPeriod
(11-25)packages/core/src/external/fhir/export/string/shared/range.ts (1)
formatRange
(10-33)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)packages/core/src/external/fhir/export/string/shared/annotation.ts (1)
formatAnnotations
(5-21)packages/core/src/external/fhir/export/string/shared/narrative.ts (1)
formatNarrative
(10-28)
packages/core/src/external/fhir/export/string/resources/location.ts (7)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
FHIRResourceToString
(8-16)defaultHasMinimumData
(3-3)packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
formatIdentifiers
(5-19)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)
formatCodeableConcepts
(78-96)formatCodeableConcept
(18-68)packages/core/src/external/fhir/export/string/shared/telecom.ts (1)
formatTelecoms
(12-27)packages/core/src/external/fhir/export/string/shared/address.ts (1)
formatAddress
(29-50)packages/core/src/external/fhir/export/string/shared/reference.ts (1)
formatReference
(28-41)
packages/core/src/external/opensearch/file/file-searcher-direct.ts (2)
packages/core/src/external/opensearch/index.ts (2)
OpenSearchConfigDirectAccess
(7-11)OpenSearchResponse
(21-25)packages/core/src/external/opensearch/index-based-on-resource.ts (1)
SearchResult
(19-19)
packages/core/src/external/fhir/export/string/shared/attachment.ts (3)
packages/core/src/util/mime.ts (1)
TXT_MIME_TYPE
(39-39)packages/core/src/external/fhir/export/string/shared/debug.ts (1)
defaultIsDebug
(1-1)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/core/src/external/fhir/export/string/shared/human-name.ts (2)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
defaultIsDebug
(1-1)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/core/src/external/opensearch/shared/bulk.ts (2)
packages/core/src/external/opensearch/text-ingestor.ts (2)
IngestRequestResource
(37-37)IngestRequest
(36-36)packages/core/src/external/opensearch/shared/id.ts (1)
getEntryId
(9-11)
packages/core/src/external/fhir/export/string/resources/diagnostic-report.ts (9)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
FHIRResourceToString
(8-16)defaultHasMinimumData
(3-3)packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
formatIdentifiers
(5-19)packages/core/src/external/fhir/export/string/shared/deny.ts (1)
emptyIfDenied
(9-15)packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
formatCodeableConcepts
(78-96)packages/core/src/external/fhir/export/string/shared/period.ts (1)
formatPeriod
(11-25)packages/core/src/external/fhir/export/string/shared/reference.ts (1)
formatReferences
(8-26)packages/core/src/external/fhir/resources/diagnostic-report.ts (1)
presentedFormsToText
(6-14)packages/core/src/external/fhir/export/string/shared/narrative.ts (1)
formatNarrative
(10-28)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/core/src/external/fhir/export/string/resources/allergy-intolerance.ts (6)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
FHIRResourceToString
(8-16)defaultHasMinimumData
(3-3)packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
formatIdentifiers
(5-19)packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)
formatCodeableConcept
(18-68)formatCodeableConcepts
(78-96)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)packages/core/src/external/fhir/export/string/shared/reference.ts (1)
formatReference
(28-41)packages/core/src/external/fhir/export/string/shared/annotation.ts (1)
formatAnnotations
(5-21)
packages/core/src/external/fhir/export/string/resources/organization.ts (6)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (1)
FHIRResourceToString
(8-16)packages/core/src/external/fhir/export/string/shared/identifier.ts (1)
formatNpiIdentifiers
(52-58)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)packages/core/src/external/fhir/export/string/shared/telecom.ts (1)
formatTelecoms
(12-27)packages/core/src/external/fhir/export/string/shared/address.ts (1)
formatAddresses
(11-27)packages/core/src/external/fhir/export/string/shared/coding.ts (1)
formatCodings
(16-34)
packages/core/src/external/fhir/export/string/shared/address.ts (2)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
defaultIsDebug
(1-1)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/utils/src/open-search/semantic-ingest.ts (5)
packages/shared/src/index.ts (1)
sleep
(13-13)packages/utils/src/shared/sentry.ts (1)
initSentry
(15-23)packages/core/src/command/patient-loader-metriport-api.ts (1)
getDomainFromDTO
(112-141)packages/core/src/command/consolidated/search/fhir-resource/ingest-lexical.ts (1)
ingestLexical
(21-53)packages/core/src/external/opensearch/shared/bulk.ts (1)
BulkResponseErrorItem
(17-23)
packages/api/src/routes/ehr/eclinicalworks/auth/middleware.ts (3)
packages/api/src/domain/jwt-token.ts (1)
JwtTokenData
(21-21)packages/api/src/routes/ehr/shared.ts (3)
ParseResponse
(17-20)processPatientRoute
(91-100)processDocumentRoute
(102-111)packages/shared/src/interface/external/ehr/eclinicalworks/jwt-token.ts (1)
eclinicalworksDashSource
(4-4)
packages/core/src/external/fhir/export/string/shared/__tests__/codeable-concept.test.ts (1)
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
formatCodeableConcept
(18-68)
packages/core/src/external/fhir/export/string/resources/medication-request.ts (11)
packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
FHIRResourceToString
(8-16)defaultHasMinimumData
(3-3)packages/core/src/external/fhir/export/string/shared/identifier.ts (2)
formatIdentifiers
(5-19)formatIdentifier
(30-44)packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (2)
formatCodeableConcept
(18-68)formatCodeableConcepts
(78-96)packages/core/src/external/fhir/export/string/shared/reference.ts (2)
formatReference
(28-41)formatReferences
(8-26)packages/core/src/external/fhir/export/string/shared/annotation.ts (1)
formatAnnotations
(5-21)packages/core/src/external/fhir/export/string/shared/dosage.ts (1)
formatDosages
(10-24)packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
formatQuantity
(11-24)packages/core/src/external/fhir/export/string/shared/duration.ts (1)
formatDuration
(7-25)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)packages/core/src/external/fhir/export/string/shared/period.ts (1)
formatPeriod
(11-25)packages/core/src/external/fhir/export/string/shared/narrative.ts (1)
formatNarrative
(10-28)
packages/core/src/external/fhir/export/string/shared/dosage.ts (7)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
defaultIsDebug
(1-1)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)packages/core/src/external/fhir/export/string/shared/timing.ts (1)
formatTiming
(11-35)packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
formatCodeableConcept
(18-68)packages/core/src/external/fhir/export/string/shared/range.ts (1)
formatRange
(10-33)packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
formatQuantity
(11-24)packages/core/src/external/fhir/export/string/shared/ratio.ts (1)
formatRatio
(10-37)
packages/core/src/external/fhir/export/string/shared/coding.ts (3)
packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)packages/core/src/external/fhir/export/string/shared/deny.ts (2)
isAllowedSystem
(18-20)emptyIfDenied
(9-15)packages/core/src/external/fhir/export/string/shared/code-display.ts (1)
codeAndDisplayToString
(3-11)
packages/core/src/external/fhir/export/string/shared/timing.ts (8)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
defaultIsDebug
(1-1)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
formatCodeableConcept
(18-68)packages/core/src/external/fhir/export/string/shared/duration.ts (1)
formatDuration
(7-25)packages/core/src/external/fhir/export/string/shared/range.ts (1)
formatRange
(10-33)packages/core/src/external/fhir/export/string/shared/period.ts (1)
formatPeriod
(11-25)packages/core/src/external/fhir/export/string/shared/numeric.ts (2)
formatNumericWithMax
(18-39)formatNumeric
(1-16)packages/core/src/external/fhir/export/string/shared/string.ts (1)
formatStrings
(3-15)
packages/core/src/external/fhir/export/string/shared/telecom.ts (2)
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
defaultIsDebug
(1-1)packages/core/src/external/fhir/export/string/shared/separator.ts (1)
FIELD_SEPARATOR
(4-4)
packages/core/src/command/ai-brief/filter.ts (2)
packages/api/src/routes/medical/schemas/fhir.ts (1)
Bundle
(23-23)packages/core/src/domain/ai-brief/modify-resources.ts (1)
SlimResource
(63-77)
packages/core/src/external/opensearch/index-based-on-file.ts (2)
packages/core/src/external/opensearch/index-based-on-resource.ts (2)
IndexFields
(3-9)SearchResult
(19-19)packages/core/src/external/opensearch/index.ts (1)
contentFieldName
(1-1)
🪛 Biome (1.9.4)
packages/core/src/external/fhir/export/string/resources/coverage.ts
[error] 107-118: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
packages/core/src/external/opensearch/lexical/lexical-search.ts
[error] 15-15: Use a regular expression literal instead of the RegExp constructor.
Regular expression literals avoid some escaping required in a string literal, and are easier to analyze statically.
Safe fix: Use a literal notation instead.
(lint/complexity/useRegexLiterals)
packages/core/src/external/html/remove-tags.ts
[error] 52-52: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
packages/core/src/external/fhir/export/string/shared/dosage.ts
[error] 45-45: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (223)
packages/core/src/external/opensearch/file/file-remover-direct.ts (1)
2-2
: Import path change looks good.The updated import path correctly reflects the new directory structure where OpenSearch file handling modules have been organized into a
file/
subdirectory.packages/core/src/external/html/remove-tags.ts (1)
41-91
: Well-structured HTML tag removal utility.This is a comprehensive and well-designed utility function that follows coding guidelines. The step-by-step regex processing approach makes it maintainable and debuggable.
🧰 Tools
🪛 Biome (1.9.4)
[error] 52-52: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
packages/api/src/command/hie/unlink-patient-from-organization.ts (1)
14-14
: Import path update aligns with directory restructuring.The updated import path correctly reflects the new OpenSearch module organization with the
file/
subdirectory. This change is consistent with the broader restructuring of OpenSearch-related modules.packages/api/src/command/medical/patient/consolidated-delete.ts (1)
17-17
: LGTM! Good architectural improvement.The import path change centralizes the consolidated patient data retrieval logic in the core package, which promotes code reuse and follows the Onion Pattern architecture. This aligns well with the broader refactoring effort to move shared functionality to the core package.
packages/utils/src/open-search/re-populate.ts (1)
6-6
: LGTM! Import path update for module restructuring.The import path update to include the additional
file/
directory segment aligns with the broader restructuring of OpenSearch-related modules. This maintains consistency across the codebase while organizing file ingestor functionality into a more structured directory hierarchy.packages/infra/lib/api-stack/ccda-search-connector.ts (1)
112-112
: LGTM! Improved URL formatting with explicit HTTPS scheme.The addition of the
"https://"
prefix to the search host environment variable ensures proper URL formatting and explicit HTTPS usage. This improvement promotes consistency across the stack and prevents potential issues with missing protocol schemes in endpoint URLs.packages/utils/src/open-search/cleanup.ts (1)
3-5
: LGTM! Consistent import path update for module restructuring.The import path update mirrors the changes in other OpenSearch-related files, maintaining consistency across the codebase. This is part of the broader restructuring effort to organize OpenSearch file ingestor functionality into a more structured directory hierarchy.
packages/core/src/external/fhir/export/string/shared/debug.ts (1)
1-1
: LGTM! Clean centralized debug configuration.The constant follows naming conventions and provides a centralized default for debug mode across FHIR string conversion utilities.
packages/core/src/external/ehr/bundle/job/create-resource-diff-bundles/steps/compute/ehr-compute-resource-diff-bundles-local.ts (2)
4-4
: LGTM! Import updated consistently with function refactoring.The import correctly reflects the new
getConsolidatedFile
function from the consolidated data retrieval refactoring.
149-149
: LGTM! Function call updated to match new API.The call to
getConsolidatedFile
is consistent with the updated import and maintains the same functionality based on the provided context.packages/lambdas/src/shared/ehr.ts (1)
37-37
: Good fix! Error message now correctly identifies the invalid field.The error message was previously incorrectly stating "Invalid patientId" when validating
departmentId
. This fix improves error clarity and debugging.packages/core/src/external/opensearch/file/file-ingestor-sqs.ts (1)
4-8
: LGTM! Import paths updated consistently for directory restructuring.The import path adjustments correctly reflect the OpenSearch module reorganization with consistent depth changes across all imports.
packages/api/src/routes/internal/jwt-token/index.ts (1)
4-4
: LGTM! Clean integration following established patterns.The new EClinicalWorks route registration follows the existing pattern perfectly, with alphabetical ordering maintained for both imports and route registrations.
Also applies to: 15-15
packages/core/src/util/config.ts (1)
65-67
: LGTM! Consistent with existing configuration pattern.The new
getLexicalSearchIndexName()
method follows the established pattern used by other configuration getters in this class, usinggetEnvVarOrFail
for required environment variables and maintaining consistent naming conventions.packages/lambdas/src/sqs-to-opensearch-xml.ts (1)
2-3
: LGTM! Import path updates align with module reorganization.The updated import paths correctly reflect the refactoring that moved OpenSearch file ingestor modules into a
file/
subdirectory structure.packages/utils/src/open-search/semantic-search.ts (1)
6-6
: LGTM! Import path correctly updated for consolidated module structure.The updated import path reflects the move of semantic search functionality from external OpenSearch modules to the consolidated command structure, aligning with the broader refactoring effort to centralize search operations.
packages/api/src/external/ehr/shared/utils/bundle/functions.ts (1)
53-53
: LGTM! Consistent EHR integration pattern.The addition of EClinicalWorks to the bundle functions mapping follows the established pattern for EHR sources that don't yet have bundle functionality implemented. The undefined value ensures proper error handling through the
getBundleFunctions
function.packages/shared/src/interface/external/ehr/eclinicalworks/index.ts (1)
1-1
: LGTM! Standard module export pattern.The re-export pattern correctly centralizes JWT token exports for EClinicalWorks, following TypeScript best practices for module organization.
packages/api/src/routes/medical/document.ts (1)
4-4
:✅ Verification successful
Verify the new import path exists and functions correctly.
The import path change aligns with the search functionality consolidation. Please ensure the
searchDocuments
function is properly exported from the new consolidated module location.
🏁 Script executed:
#!/bin/bash # Verify that the searchDocuments function exists at the new import path ast-grep --pattern 'export { searchDocuments }' ast-grep --pattern 'export const searchDocuments' ast-grep --pattern 'export function searchDocuments'Length of output: 156
🏁 Script executed:
#!/bin/bash set -e # Locate the document-reference search module directory under core/command/consolidated dirs=$(fd -t d 'packages/core/command/consolidated/search/document-reference') echo "Found directory(s):" echo "$dirs" # For each found directory, list its files and search for searchDocuments for d in $dirs; do echo "---- Files in $d ----" find "$d" -maxdepth 1 -type f -print echo "---- Grep for searchDocuments in $d ----" rg 'searchDocuments' "$d" || true doneLength of output: 148
🏁 Script executed:
#!/bin/bash set -e echo "🔍 Searching for definitions of 'searchDocuments' in TypeScript files" rg -nE 'export\s+(?:const|function)\s+searchDocuments' -g '*.ts' || true echo -e "\n🔄 Searching for any re-exports of 'searchDocuments'" rg -n 'export\s*{[^}]*searchDocuments' -g '*.ts' || true echo -e "\n📁 Listing all 'document-reference' directories" fd -t d document-reference || trueLength of output: 1154
🏁 Script executed:
#!/bin/bash set -e base="packages/core/src/command/consolidated/search/document-reference" echo "📂 Listing all files under $base:" find "$base" -type f -print echo -e "\n🔍 Searching for any occurrence of 'searchDocuments' in the above files:" rg -n "searchDocuments" "$base" || trueLength of output: 1003
Import Path Verified:
searchDocuments
Export ExistsThe
searchDocuments
function is indeed exported from
packages/core/src/command/consolidated/search/document-reference/search.ts
(see line 27), so the importimport { searchDocuments } from "@metriport/core/command/consolidated/search/document-reference/search";is valid. No further changes needed.
packages/api/src/external/cda/generate-ccd.ts (2)
18-18
: LGTM! Import reordering is fine.The reordering of the
normalizeBundle
import doesn't affect functionality and maintains the same relative path.
2-2
:✅ Verification successful
Verify the consolidated import path and approve the refactoring.
The import path change to the consolidated module aligns with the broader refactoring effort. Please ensure the function is properly exported from the new location.
🏁 Script executed:
#!/bin/bash # Verify that getConsolidatedPatientData is exported from the consolidated module ast-grep --pattern 'export { getConsolidatedPatientData }' ast-grep --pattern 'export const getConsolidatedPatientData' ast-grep --pattern 'export function getConsolidatedPatientData'Length of output: 189
Let’s locate the
consolidated-get
module and inspect its exports to confirm thatgetConsolidatedPatientData
is indeed exposed:
🏁 Script executed:
#!/bin/bash # 1. List all files named consolidated-get*.ts to find the module echo "=== Finding consolidated-get files ===" fd "consolidated-get" -e ts -t f # 2. Search for any definition or export of getConsolidatedPatientData within the core package echo -e "\n=== Searching for getConsolidatedPatientData references ===" rg -n "getConsolidatedPatientData" packages/core # 3. For each consolidated-get file found, print the first 200 lines to inspect exports echo -e "\n=== Inspecting module exports ===" for f in $(fd "consolidated-get" -e ts -t f); do echo -e "\n---- $f ----" sed -n '1,200p' "$f" doneLength of output: 22081
✅ Confirmed:
getConsolidatedPatientData
export exists in core module and the new import path is valid.
No further changes required.packages/infra/lib/api-stack.ts (1)
583-583
: LGTM! Explicit HTTPS prefix improves security and clarity.Adding the explicit "https://" prefix removes protocol ambiguity and ensures secure communication with the search endpoint. This is a good security practice that aligns with the infrastructure updates mentioned in the summary.
packages/infra/config/env-config.ts (1)
270-272
: LGTM! Consistent configuration pattern.The addition of EClinicalWorks configuration follows the established pattern used by other EHR integrations, with the
env
field properly typed as a string. The integration fits well within the existingehrIntegration
structure.packages/api/src/errors/index.ts (1)
10-12
: Good deprecation practice.The JSDoc deprecation comment properly guides developers to use the centralized error handling utility while maintaining backward compatibility. This supports the gradual migration to shared utilities.
packages/shared/src/interface/external/ehr/source.ts (1)
6-6
: LGTM! Consistent enum addition.The addition of
eclinicalworks
follows the established naming convention and automatically extends the derived types and arrays. The implementation maintains consistency with existing EHR sources.packages/api/src/external/ehr/shared/utils/mappings.ts (1)
27-27
: LGTM! Consistent mapping pattern.The addition of EClinicalWorks to the schema map with
undefined
follows the same pattern as Canvas, maintaining type safety while indicating no secondary mappings are currently defined for this EHR source.packages/core/src/external/opensearch/file/file-search-connector-factory.ts (2)
8-8
: LGTM! Import path updated for directory restructuring.The import path correctly reflects the new directory structure after the OpenSearch module reorganization.
34-34
:✅ Verification successful
Verify that Config.getSearchEndpoint() returns complete URLs.
The removal of the
"https://" +
prefix suggests thatConfig.getSearchEndpoint()
now returns complete URLs including the protocol. Please verify this assumption is correct and consistent across the codebase.Also applies to: 49-49
🏁 Script executed:
#!/bin/bash # Description: Verify that Config.getSearchEndpoint() returns complete URLs with protocol # Expected: All usages should be consistent with the new pattern echo "=== Searching for Config.getSearchEndpoint() usage ===" rg -A 2 -B 2 "Config\.getSearchEndpoint\(\)" echo -e "\n=== Searching for https:// + endpoint patterns ===" rg -A 2 -B 2 "https.*endpoint|endpoint.*https" echo -e "\n=== Checking Config class implementation ===" ast-grep --pattern 'static getSearchEndpoint(): string { $$$ }'Length of output: 31251
Here’s a script to locate where
getSearchEndpoint
is defined and inspect its body:
🏁 Script executed:
#!/bin/bash echo "=== Locate getSearchEndpoint references ===" rg -n "getSearchEndpoint" -R "packages/core/src" echo -e "\n=== Locate Config class definition ===" rg -n "class Config" -R "packages/core/src"Length of output: 1090
Let’s correct the ripgrep usage and pull in some context around the method definition:
🏁 Script executed:
#!/bin/bash echo "=== Locating getSearchEndpoint method definition ===" rg -n -C 5 "static getSearchEndpoint" packages/core/src echo -e "\n=== Locating Config class declaration ===" rg -n -C 5 "class Config" packages/core/srcLength of output: 1778
Ensure SEARCH_ENDPOINT includes the protocol
Config.getSearchEndpoint() simply returns the raw SEARCH_ENDPOINT env var (packages/core/src/util/config.ts:49–51), so the removedhttps://
prefix means your deployments and CI/CD must now set SEARCH_ENDPOINT to a full URL (e.g.https://search.example.com
).• packages/core/src/util/config.ts – getSearchEndpoint returns getEnvVarOrFail("SEARCH_ENDPOINT") without adding
https://
• Verify all environment configurations, README or deployment scripts now supplyhttps://…
in SEARCH_ENDPOINTNo code changes needed; just confirm all configs have been updated.
packages/core/src/external/aws/document-signing/bulk-sign.ts (1)
11-11
: LGTM! Import path updated for consolidated architecture.The import path change aligns with the broader refactoring to consolidate search functionality under the unified command structure. The function interface remains the same, ensuring backward compatibility.
packages/core/src/external/opensearch/shared/id.ts (1)
1-12
: LGTM! Clean utility function with good documentation.The
getEntryId
function implementation is correct and well-documented. The concatenation approach using underscores creates unique identifiers as intended.packages/core/src/command/consolidated/get-snapshot.ts (1)
7-7
: LGTM! Explicit type definition improves clarity.Making the
undefined
type explicit in the optional property is a good TypeScript practice that enhances code clarity and aligns with strict typing standards.packages/api/src/external/carequality/document/process-outbound-document-retrieval-resps.ts (2)
11-11
: LGTM! Import path updated for consolidated architecture.The import path change from relative
../../aws/opensearch
to the consolidated module@metriport/core/command/consolidated/search/document-reference/ingest
aligns with the architectural refactoring effort.
303-303
: LGTM! Function call updated to match new signature.The change from passing the full
mergedFHIRDocRef
object to justmergedFHIRDocRef.id
correctly aligns with the updatedingestIntoSearchEngine
function signature, which now expects anentryId: string
as the second parameter instead of a complete document reference object.packages/core/src/command/consolidated/snapshot-on-s3.ts (1)
35-35
: LGTM! Type annotation improvement.Making the optional nature of
requestId
explicit withstring | undefined
is a good TypeScript practice that improves type safety and clarity.packages/core/src/domain/ai-brief/modify-resources.ts (2)
56-56
: LGTM! Useful 3D11 addition to cleanup patterns.Adding
"<content/>"
to the removal list enhances the note cleanup functionality for better text processing.
591-591
: LGTM! Good refactoring for reusability.Exporting
cleanUpNote
enables its reuse across other modules, which follows the DRY principle and improves modularity.packages/api/src/routes/ehr/index.ts (2)
11-12
: LGTM! Consistent import pattern.The import statements follow the established pattern for EHR integrations with clear naming conventions.
32-32
: LGTM! Proper route registration.The route registration follows the established middleware chain pattern used by other EHR integrations, ensuring consistent authentication and access control.
packages/core/src/external/fhir/__tests__/bundle.ts (1)
22-27
: LGTM! Enhanced FHIR bundle compliance.Adding the
total
property when entries are present makes the test bundles more realistic and compliant with FHIR standards. The conditional logic ensures proper bundle structure.packages/core/src/external/opensearch/shared/filters.ts (1)
1-3
: LGTM! Clean utility function implementation.This utility function correctly creates OpenSearch filter objects for patient identification. The implementation is simple, well-typed, and follows the coding guidelines. The function name is descriptive and uses proper camelCase naming.
packages/api/src/external/commonwell/document/document-query.ts (2)
38-38
: Good refactoring: Moving to absolute package import.The change from a relative import to an absolute package import improves modularity and aligns with the broader restructuring of OpenSearch functionality mentioned in the AI summary.
711-711
:✅ Verification successful
Verify the function signature change is correct.
The function call has been modified to pass
fhirDocRef.id
instead of the entirefhirDocRef
object. While the AI summary indicates this aligns with similar changes in related files, please ensure that theingestIntoSearchEngine
function signature expects a document reference ID as the first parameter.
🏁 Script executed:
#!/bin/bash # Description: Verify the function signature of ingestIntoSearchEngine to confirm it expects a document reference ID # Search for the function definition ast-grep --pattern $'export function ingestIntoSearchEngine($_, $$$) { $$$ }' # Also search for function declarations/interfaces rg -A 10 "ingestIntoSearchEngine.*function|function.*ingestIntoSearchEngine"Length of output: 1261
🏁 Script executed:
#!/bin/bash rg -n "ingestIntoSearchEngine" -A5 -B5 packages/api/src/external/commonwell/document/document-query.tsLength of output: 1330
Confirmed matching signature—no change needed
The
ingestIntoSearchEngine
function in
packages/core/src/command/consolidated/search/document-reference/ingest.ts
is declared as:export async function ingestIntoSearchEngine( patient: Pick<Patient,"id"|"cxId">, entryId: string, // <— expects a string ID here file: { key:string; bucket:string; contentType?:string }, requestId: string, log = out(`ingestIntoSearchEngine`).log ): Promise<void> { … }And in
packages/api/src/external/commonwell/document/document-query.ts
you now correctly passfhirDocRef.id
(a string) as theentryId
argument.No further updates required.
packages/core/src/external/fhir/consolidated/consolidated.ts (1)
18-18
: Good type clarification improvement.The explicit inclusion of
undefined
in the type annotation improves clarity, even though optional properties already includeundefined
by default in TypeScript. This change enhances code readability and aligns with similar explicit typing improvements mentioned in the AI summary.packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-factory.ts (1)
5-6
: Factory function implementation looks good.The function correctly implements the factory pattern, follows naming conventions, and returns the appropriate interface type. The current implementation provides a working solution while allowing for future extensibility.
packages/core/src/external/fhir/codeable-concept.ts (1)
44-45
: LGTM! Improved type safety and defensive programming.The parameter type change to accept
string | undefined
and the early guard clause improve the function's robustness by handling falsy inputs gracefully. This prevents potential runtime errors and makes the function more defensive.packages/infra/lib/api-stack/api-service.ts (2)
335-336
: Environment variable addition for lexical search with migration note.The addition of
LEXICAL_SEARCH_INDEX
follows the established pattern. The TODO comment indicates this is temporary until lambda functions handle lexical search functionality.
365-365
: EClinicalWorks environment variable integration.The addition of
EHR_ECLINICALWORKS_ENVIRONMENT
properly integrates the new EClinicalWorks EHR support into the API service environment configuration.packages/core/src/external/fhir/export/string/shared/age.ts (1)
1-18
: Well-implemented FHIR Age formatting utility.The implementation correctly treats Age as a special case of Quantity and delegates to the existing
formatQuantity
function. The function follows the established patterns in the codebase:
- Consistent parameter destructuring with other formatting utilities
- Proper TypeScript typing with FHIR types
- Clear JSDoc documentation explaining the Age-Quantity relationship
- Functional programming style with single responsibility
packages/api/src/external/ehr/shared/utils/jwt-token.ts (3)
15-18
: Proper import integration for EClinicalWorks JWT tokens.The import follows the established pattern for other EHR providers, maintaining consistency in the codebase structure.
37-37
: Consistent addition to JWT token sources array.Adding
eclinicalworksDashSource
to theehrDashJwtTokenSources
array follows the same pattern used for other EHR providers, ensuring proper recognition of EClinicalWorks tokens.
48-49
: Proper union type extension for EClinicalWorks.The addition of
EClinicalWorksDashJwtTokenData
to theEhrDashJwtTokenData
union type correctly extends type safety to cover EClinicalWorks JWT tokens, maintaining consistency with the existing pattern.packages/core/src/external/fhir/export/string/shared/code-display.ts (1)
3-11
: LGTM! Well-implemented utility function.The function logic correctly handles all combinations of code and display presence, uses proper early returns, and follows functional programming principles. The implementation is clean and deterministic.
packages/core/src/external/fhir/export/string/shared/string.ts (1)
3-15
: LGTM! Excellent adherence to coding guidelines.The function properly uses destructured parameters, implements early returns, and follows functional programming principles. The debug labeling logic is clear and the TypeScript types are appropriate.
packages/core/src/command/consolidated/consolidated-filter.ts (5)
2-2
: LGTM: Appropriate import for timing measurement.The addition of
elapsedTimeFromNow
import supports the new timing measurement functionality added later in the file.
18-18
: LGTM: Function name clarification.The rename from
getConsolidated
togetConsolidatedFile
provides better clarity about what the function returns and aligns with the updated function signature shown in the relevant code snippets.
60-60
: LGTM: Consistent usage of renamed function.The function call correctly uses the renamed
getConsolidatedFile
function, maintaining consistency with the import change.
97-103
: LGTM: Excellent addition of timing measurement and logging.The timing measurement provides valuable observability for performance monitoring of the
addMissingReferencesFn
operation. The implementation correctly uses the importedelapsedTimeFromNow
utility and provides clear, informative logging.
120-125
: LGTM: Improved bundle integrity with correct total field.This refactoring ensures that the
total
field accurately reflects the number of entries in the bundle after adding missing references. Creating thenewEntries
array first and then assigning bothtotal
andentry
fields ensures consistency and maintains FHIR bundle integrity.packages/core/src/external/fhir/export/string/fhir-resource-to-string.ts (2)
3-3
: LGTM: Well-defined default constant.The
defaultHasMinimumData
cons F438 tant provides a clear default value for tracking whether resources contain sufficient data for string representation. Thefalse
default is conservative and appropriate.
12-15
: LGTM: Backward-compatible interface enhancement.The addition of the optional
isDebug
parameter to thetoString
method enhances the interface while maintaining backward compatibility. The updated JSDoc clearly documents the parameter's purpose for including debug information like property labels.packages/core/src/external/opensearch/file/file-ingestor.ts (3)
1-2
: LGTM: Configuration type standardization.The import changes standardize the use of
OpenSearchConfig
from the parent directory and update theIndexFields
import path. This aligns with the broader OpenSearch module refactoring mentioned in the AI summary.
10-10
: LGTM: Consistent type alias update.The type alias correctly uses the standardized
OpenSearchConfig
type, maintaining consistency with the import changes.
17-17
: LGTM: Type clarification improves code readability.Making the
contentType
parameter type more explicit asstring | undefined
rather than just optional string improves code clarity without changing the method's logic or behavior.packages/core/src/external/opensearch/shared/delete.ts (1)
1-14
: LGTM: Clean and focused delete query utility.This new module provides a well-structured utility for creating OpenSearch delete queries. The implementation demonstrates good practices:
- Clear type definition:
DeleteParams
clearly defines the required parameters- Reusability: Leverages the existing
getPatientFilters
function from the shared filters module- Proper structure: Returns a correctly formatted OpenSearch bool query with must clauses
- Focused responsibility: Single-purpose module that does one thing well
The integration with
getPatientFilters
ensures consistency with other query construction patterns in the codebase.packages/shared/src/interface/external/ehr/eclinicalworks/jwt-token.ts (1)
1-10
: LGTM! Clean zod schema implementation.The JWT token schema is well-structured and follows TypeScript best practices. The use of
z.literal()
for source validation ensures type safety, and the naming conventions align with the coding guidelines.packages/api/src/command/jwt-token.ts (1)
55-70
: LGTM! Well-implemented ID-based JWT token retrieval functions.The new functions
getJwtTokenById
andgetJwtTokenByIdOrFail
follow the established patterns in this module perfectly:
- Consistent naming conventions and documentation
- Proper error handling with
NotFoundError
- Clear indication that expiration is not checked
- Good TypeScript usage with proper return types
The implementation aligns well with the existing codebase structure and coding guidelines.
packages/core/src/external/opensearch/file/file-searcher.ts (1)
1-12
: LGTM! Clean and well-designed interface.The
OpenSearchFileSearcher
interface andSearchRequest
type are well-structured:
- Clear separation of concerns with focused interface
- Good documentation referencing Elasticsearch query syntax
- Proper TypeScript typing with meaningful names
- Follows functional programming principles with clear input/output contract
The design aligns with the coding guidelines for minimizing coupling and building deterministic functions.
packages/core/src/external/opensearch/index-based-on-file.ts (1)
1-12
: LGTM! Well-structured type definitions with good architectural consistency.The type definitions follow the established pattern from
index-based-on-resource.ts
while being appropriately adapted for file-based indexing. The use of computed property names for the content field and the proper omission of sensitive content from search results demonstrates good design practices.packages/core/src/util/error/shared.ts (1)
62-67
: Consider consistent parameter naming.The returned function uses
error
as the parameter name, which is more descriptive thanerr
used in some deprecated functions above. This follows the coding guidelines for meaningful naming.packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.ts (1)
1-15
: LGTM! Clean and well-designed interface.The type definitions and interface follow TypeScript best practices with meaningful naming, appropriate use of optional properties, and proper destructuring in the method signature. The interface design is clean and follows the coding guidelines for functional programming style with clear input/output types.
packages/api/src/shared/config.ts (1)
335-337
: LGTM! Consistent implementation following established patterns.The new
getEClinicalWorksEnv()
method follows the same pattern as other EHR environment getters in the class. UsinggetEnvVar()
instead ofgetEnvVarOrFail()
appropriately indicates this is optional configuration, consistent with other EHR integrations.packages/api/src/routes/ehr/eclinicalworks/routes/dash.ts (3)
1-13
: LGTM! Well-structured imports following coding guidelines.The imports follow the coding guidelines with kebab-case file names and meaningful import organization. The structure is clean and follows TypeScript best practices.
28-37
: Good use of skip paths for document downloads.The implementation correctly uses skip paths for document download URLs, allowing these endpoints to bypass patient ID checks when appropriate. The middleware chain is well-structured.
20-27
:✅ Verification successful
Verify middleware execution order for security.
The middleware chain appears correctly ordered with parameter handling, route processing, ID validation, and authorization. However, ensure that the
processEhrPatientId
middleware properly validates the token-derived patient ID against the request parameters to prevent unauthorized access.
🏁 Script executed:
#!/bin/bash # Description: Verify the middleware chain and security validations # Search for processEhrPatientId implementation to understand security checks ast-grep --pattern 'export function processEhrPatientId($$$) { $$$ }' # Look for ForbiddenError usage to confirm proper authorization rg -A 3 "ForbiddenError" packages/api/src/routes/ehr/shared.tsLength of output: 925
Middleware chain and patient ID validation verified
The ordering of
handleParams
,processPatientRoute
,processEhrPatientId
,patientAuthorization
, andmedicalPatient
is correct. TheprocessEhrPatientId
middleware inpackages/api/src/routes/ehr/shared.ts
throws aForbiddenError
when the token-derived patient ID does not match the request parameter, ensuring proper security. No changes required.packages/core/src/external/fhir/export/string/shared/range.ts (3)
6-9
: Excellent JSDoc documentation.The function documentation clearly explains the purpose and structure of a FHIR Range, making the code more maintainable.
10-18
: Well-designed function signature following coding guidelines.The function follows the coding guidelines perfectly:
- Uses destructured parameters instead of multiple parameters
- Meaningful parameter names
- Proper TypeScript typing with undefined handling
- Default parameter for
isDebug
using shared constant
19-33
: Robust implementation with proper edge case handling.The function correctly handles:
- Early return for undefined range
- Conditional inclusion of low/high values
- Proper array building and joining
- Consistent formatting with debug labeling
- Uses shared separator constant for consistency
The logic is deterministic and follows functional programming principles.
packages/core/src/external/opensearch/shared/log.ts (2)
4-4
: Good type definition for log levels.The
OpenSearchLogLevel
type clearly defines the available logging levels with meaningful string literals.
6-15
: Well-implemented conditional logging with proper type safety.The function design is excellent:
- Uses proper TypeScript return type annotation
- Handles all log levels correctly with conditional logic
- Maintains consistency with the original logger interface
- Uses
emptyFunction
from shared package for no-op behavior- Follows functional programming principles
The implementation is deterministic and follows the coding guidelines for preferring
const
and using meaningful names.packages/core/src/external/opensearch/index-based-on-resource.ts (3)
3-9
: Well-defined IndexFields type with proper resource identifiers.The type definition correctly uses:
- Meaningful field names (
cxId
,patientId
,resourceType
,resourceId
)- Dynamic content field using the shared constant
- Proper TypeScript string typing
- Consistent with resource-based indexing approach
This aligns well with the coding guidelines for meaningful names and TypeScript usage.
11-17
: Correct OpenSearch field type mappings.The index definition properly maps:
- ID fields as "keyword" type for exact matching
- Content field as "text" type for full-text search
- All fields from IndexFields are covered
This follows OpenSearch best practices for field types based on intended usage.
19-19
: Clean SearchResult type definition.The
SearchResult
type correctly omits the content field fromIndexFields
, which makes sense for search results where you typically don't need the full content. This follows TypeScript utility type best practices.packages/api/src/routes/ehr/shared.ts (2)
25-25
: LGTM: Function signature enhancement for token processing.The addition of the
tokenId
parameter to theparseExternalId
callback enhances the token processing capabilities by providing additional context. This change aligns with the EClinicalWorks JWT token handling improvements mentioned in the PR.
31-32
: LGTM: Clean implementation of token ID extraction and usage.The extraction of
tokenId
fromauthInfo.id
and its subsequent use in theparseExternalId
call is well-implemented. This enhancement provides the necessary token context for the downstream processing while maintaining the existing error handling patterns.packages/core/src/external/fhir/export/string/resources/location.ts (1)
13-74
: LGTM: Well-structured FHIR Location resource converter.The implementation follows the established patterns from other FHIR resource converters in the codebase. Key strengths:
- Consistent use of shared formatting functions (
formatIdentifiers
,formatCodeableConcepts
, etc.)- Proper debug mode support with conditional labeling
- Appropriate minimum data validation logic
- Clean separation of concerns and modular approach
The
hasMinimumData
tracking ensures meaningful output by requiring at least one of: name, aliases, description, or address to be present.packages/api/src/external/ehr/eclinicalworks/shared.ts (2)
9-20
: LGTM: Solid environment validation with meaningful error handling.The
getEClinicalWorksEnv
function provides robust validation with clear error messages. The use ofMetriportError
with additional context ({ environment }
) follows the coding guidelines for error handling.
22-24
: LGTM: Clean type extension pattern.The
EClinicalWorksPerPracticeParams
type properly extends the baseEhrPerPracticeParams
with the additionalauthToken
field. This follows good TypeScript practices for type composition.packages/core/src/external/fhir/export/string/resources/organization.ts (3)
13-13
: LGTM: Consistent interface implementation with debug support.The updated method signature correctly implements the
FHIRResourceToString<Organization>
interface with the optionalisDebug
parameter, maintaining consistency with other FHIR resource converters.
16-17
: LGTM: Appropriate use of NPI-specific identifier formatting.Using
formatNpiIdentifiers
for organizations is appropriate since NPI (National Provider Identifier) is the most relevant identifier type for healthcare organizations.
19-37
: LGTM: Consistent debug mode implementation and shared function usage.The implementation effectively uses shared formatting functions (
formatTelecoms
,formatAddresses
,formatCodings
) while providing consistent debug mode support with conditional labeling. This aligns well with the broader FHIR string conversion refactoring effort.packages/core/src/external/fhir/export/string/shared/__tests__/timing.test.ts (7)
1-3
: LGTM! Clean imports and proper test setup.The imports are correctly structured with external dependency first, followed by the function under test.
5-7
: LGTM! Proper edge case testing.Testing undefined input is essential for robust error handling.
9-14
: LGTM! Good test coverage for basic timing events.The test correctly validates formatting of multiple timing events with proper expected output.
23-35
: LGTM! Excellent test coverage for complex repeat rules.This test validates proper formatting of frequency, period, periodUnit, and dayOfWeek fields in debug mode with correct expected output.
79-101
: LGTM! Comprehensive integration test.This test validates that all timing components (events, repeat rules, and codes) are properly formatted together.
136-163
: LGTM! Thorough testing of complex repeat rules.This test covers all possible repeat rule properties including bounds, counts, durations, frequencies, periods, days, times, when clauses, and offset. The expected output correctly formats all these components.
165-174
: LGTM! Good edge case handling.Testing empty arrays ensures the function handles edge cases gracefully by returning undefined.
packages/core/src/command/consolidated/search/fhir-resource/ingest-semantic.ts (5)
1-8
: LGTM! Clean imports with proper organization.The imports are well-organized with domain imports first, followed by external utilities, and proper destructuring of specific functions.
9-14
: LGTM! Excellent documentation.The JSDoc comment clearly explains the function's purpose and parameters, following documentation best practices.
15-21
: LGTM! Function signature follows coding guidelines.The function properly uses destructuring for parameters as recommended in the coding guidelines, with clear typing.
22-24
: LGTM! Proper logging setup and data retrieval.The logging setup includes context (cx and pt) and the consolidated data retrieval follows the expected pattern.
26-33
: LGTM! Good configuration pattern.The OpenSearchTextIngestor configuration properly uses the Config utility for all required settings, with appropriate log level.
packages/core/src/external/fhir/export/string/shared/narrative.ts (4)
1-4
: LGTM! Clean imports and proper dependencies.The imports are well-organized with external types first, followed by internal utilities.
7-18
: LGTM! Excellent function documentation and signature.The JSDoc comment is clear and the function signature follows coding guidelines with proper destructuring and optional parameters.
19-21
: LGTM! Proper early returns and edge case handling.The function correctly handles undefined narratives and empty content after filtering.
22-28
: LGTM! Clean conditional formatting logic.The debug mode implementation is well-structured with clear conditional formatting for both status and content.
packages/core/src/external/fhir/export/string/shared/deny.ts (2)
1-1
: LGTM! Good expansion of denied text values.The addition of "Note" and "History and physical note" to the denied text list makes sense for filtering out non-informative content.
6-9
: LGTM! Improved function naming and documentation.The rename from
checkDeny
toemptyIfDenied
is more descriptive and the JSDoc comment clearly explains the function's behavior.packages/core/src/external/fhir/export/string/resources/coverage.ts (1)
14-142
: LGTM! Well-structured Coverage converter implementation.The implementation follows excellent patterns:
- Consistent use of helper functions for formatting
- Proper debug mode support throughout
- Appropriate minimum data validation
- Good separation of concerns with field-specific formatting
- Proper error handling with early return
The complex nested logic for classes and costs is well-structured and handles edge cases appropriately.
🧰 Tools
🪛 Biome (1.9.4)
[error] 107-118: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
packages/core/src/external/fhir/resources/diagnostic-report.ts (3)
6-14
: LGTM! Clean and efficient text extraction.The
presentedFormsToText
function correctly usesflatMap
to handle the array transformation and filtering in a functional style, which aligns with the coding guidelines.
21-28
: LGTM! Proper validation and multi-stage cleanup.The function correctly:
- Validates data presence with early return
- Filters by language (English only) for consistency
- Applies multi-stage text cleanup for better quality output
- Uses existing utility functions appropriately
30-33
: LGTM! Appropriate additional cleanup.The HTML tag removal and question mark sequence cleanup provide good additional sanitization of the extracted text.
packages/api/src/routes/internal/jwt-token/eclinicalworks.ts (4)
18-29
: LGTM! Clean GET endpoint implementation.The endpoint correctly:
- Uses request logging middleware
- Extracts authorization token properly
- Delegates to shared utility for consistent token checking
- Returns appropriate HTTP status and JSON response
31-34
: LGTM! Proper request validation schema.The Zod schema correctly validates the required fields and uses the imported EClinicalWorks-specific schema for type safety.
39-52
: LGTM! Well-structured POST endpoint.The endpoint implementation follows best practices:
- Proper request validation with Zod
- Token extraction using shared utility
- Consistent use of asyncHandler for error handling
- Appropriate HTTP status response
- Spread operator usage for clean parameter passing
1-11
: LGTM! Proper imports and dependencies.All imports are well-organized and necessary for the functionality. The use of shared utilities and schemas promotes consistency across the codebase.
packages/core/src/external/opensearch/file/file-searcher-direct.ts (4)
7-7
: LGTM! Simplified configuration type.The direct aliasing of
OpenSearchConfigDirectAccess
eliminates unnecessary type complexity while maintaining the same interface contract.
51-51
: LGTM! Enhanced type safety with generics.Adding the
SearchResult
generic parameter toOpenSearchResponse
improves type checking and makes the response type more explicit.
57-57
: LGTM! Consistent method signature update.The
mapResult
method signature correctly reflects the enhanced typing from the response type improvement.
2-5
: LGTM! Clean import organization.The import consolidation improves readability while maintaining all necessary dependencies.
packages/core/src/external/fhir/export/string/shared/period.ts (1)
11-25
: LGTM! Well-executed refactoring following established patterns.The function signature refactoring is excellent and consistent with the broader FHIR string export improvements:
- Clean object destructuring with meaningful parameter names
- Proper undefined handling for missing or incomplete period data
- Conditional debug labeling that maintains backward compatibility
- Follows TypeScript coding guidelines for parameter destructuring
packages/core/src/external/fhir/export/string/resources/patient.ts (1)
12-29
: Excellent refactoring implementation!The PatientToString class updates perfectly align with the broader FHIR string export improvements:
- Proper implementation of the updated
FHIRResourceToString<Patient>
interface- Clean object-based parameter passing to formatting functions
- Appropriate conditional labeling for debug mode
- Maintains backward compatibility with existing functionality
The code follows TypeScript guidelines well with proper destructuring and meaningful variable names.
packages/core/src/external/fhir/export/string/shared/reference.ts (2)
8-26
: LGTM! Clean implementation following best practices.The
formatReferences
function correctly implements the object parameter pattern preferred by the coding guidelines and handles edge cases appropriately. The use offlatMap
with the nullish coalescing operator?? []
is an elegant way to filter out undefined formatted references.
28-41
: LGTM! Consistent implementation with proper null handling.The
formatReference
function follows the same patterns asformatReferences
and properly validates the reference display value with trimming and length checks to avoid returning empty strings.packages/core/src/external/fhir/export/string/resources/communication.ts (1)
12-22
: LGTM! Proper class structure and status handling.The class correctly implements the
FHIRResourceToString
interface and follows the established pattern for conditional debug labeling.packages/core/src/external/fhir/export/string/shared/ratio.ts (1)
10-37
: LGTM! Consistent implementation following established patterns.The
formatRatio
function correctly follows the same object parameter pattern and debug labeling approach used throughout the shared formatting utilities. The logic properly handles undefined ratios and returns undefined when no meaningful parts can be formatted.packages/utils/src/open-search/semantic-ingest.ts (2)
6-8
: LGTM! Clean transition from semantic to lexical ingestion.The import changes correctly replace the semantic ingestion with lexical ingestion and add the necessary bulk error handling types.
40-44
: LGTM! Good error logging setup.The output folder initialization and file path construction follow good practices for organizing error logs by context and patient ID.
packages/core/src/external/fhir/export/string/shared/quantity.ts (1)
11-24
: LGTM: Well-designed API refactoring.The refactoring to use a single object parameter improves the function's usability and follows the coding guidelines for parameter destructuring. The implementation correctly handles edge cases and maintains backward compatibility through optional parameters.
The logic properly:
- Returns
undefined
for falsy values (maintains type safety)- Constructs quantity strings without trailing spaces when unit is missing
- Conditionally includes debug labels
packages/core/src/external/opensearch/lexical/lexical-search.ts (1)
13-60
: Well-structured lexical search query builder.The implementation provides a clean abstraction for building OpenSearch queries with appropriate:
- Conditional query strategies (match vs simple_query_string)
- Field exclusions to optimize response size
- Patient-specific filtering integration
The dual query approach based on the
$
prefix provides flexibility for different search scenarios.🧰 Tools
🪛 Biome (1.9.4)
[error] 15-15: Use a regular expression literal instead of the RegExp constructor.
Regular expression literals avoid some escaping required in a string literal, and are easier to analyze statically.
Safe fix: Use a literal notation instead.(lint/complexity/useRegexLiterals)
packages/core/src/external/fhir/export/string/shared/duration.ts (1)
7-25
: Consistent and well-implemented duration formatter.The implementation follows the established pattern for FHIR formatting utilities with:
- Object parameter destructuring (following guidelines)
- Proper undefined handling
- Consistent debug labeling approach
- Clean string construction logic
packages/api/src/external/ehr/shared/utils/client.ts (1)
3-3
: LGTM: Clean extension of EHR client types.The changes properly extend the type system to support new EHR providers:
- Added imports for
EClinicalWorksEnv
andHealthieEnv
- Extended
EhrEnv
union type consistently- Renamed
EhrClient
toEhrClientTwoLeggedAuth
for better clarity about authentication type- Updated generic constraints accordingly
The modifications maintain backward compatibility while enabling support for additional EHR systems.
Also applies to: 5-5, 13-13, 25-25, 57-57
packages/api/src/routes/medical/patient.ts (2)
3-4
: LGTM! Centralized imports improve modularity.The imports align with the centralization effort mentioned in the PR objectives, moving logic from local implementations to shared core modules.
201-201
:✅ Verification successful
Verify backward compatibility of the simplified search implementation.
The new implementation using
makeSearchConsolidated().search({ patient, query })
is much simpler than the previous conditional logic. Please ensure this maintains the same search functionality and API response format.
🏁 Script executed:
#!/bin/bash # Description: Check if there are any breaking changes in the search response format # Expected: Consistent response structure between old and new implementations # Look for any response format definitions or types rg -A 5 -B 5 "search.*response|SearchResponse|SearchResult" packages/core/src/command/consolidated/search/ # Check for any migration notes or compatibility considerations rg -A 3 -B 3 "backward.*compatible|breaking.*change|migration" packages/core/src/command/consolidated/search/Length of output: 10786
🏁 Script executed:
#!/bin/bash # Locate and inspect the definition of `makeSearchConsolidated` to verify its return type rg -n -A10 -B10 "makeSearchConsolidated" packages/apiLength of output: 3429
🏁 Script executed:
#!/bin/bash # Inspect the factory for consolidated search to verify its behavior and return types rg -n -A50 -B5 "export function makeSearchConsolidated" -A50 packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-factory.tsLength of output: 588
🏁 Script executed:
#!/bin/bash # Inspect the SearchConsolidatedDirect implementation to verify `search` behavior and return type sed -n '1,200p' packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-direct.ts # Inspect the SearchConsolidated interface/type definition sed -n '1,200p' packages/core/src/command/consolidated/search/fhir-resource/search-consolidated.tsLength of output: 3536
No backward‐compatibility issues detected
makeSearchConsolidated()
still returnsSearchConsolidatedDirect
, which mirrors the old conditional logic (searchLexical
ifquery
is set;getConsolidatedPatientData
otherwise).- The
search()
method continues to return the sameSearchConsolidatedResult
shape ({ url?: string; resourceCount: number }
).- The API route now simply forwards that result as JSON with status 200.
I did not find any migration notes or response‐format changes in the consolidated‐search code. The new implementation preserves both behavior and response schema.
packages/core/src/external/fhir/export/string/shared/__tests__/codeable-concept.test.ts (3)
1-13
: LGTM! Well-structured imports and constants.The imports are properly organized and include all necessary dependencies for comprehensive testing.
102-150
: Excellent test coverage for text deduplication logic.These tests comprehensively cover the complex text deduplication scenarios, ensuring the function correctly handles overlapping text and coding display values.
154-173
: Helper functions are well-designed.The
getSystem()
andmakeCodeAndDisplay()
functions provide good test data generation with realistic values.packages/core/src/external/fhir/export/string/resources/related-person.ts (2)
10-16
: LGTM! Clean class structure following established patterns.The class implements the interface correctly and follows the same pattern as other resource converters in the codebase.
28-36
: Good use of minimum data tracking for relationship.The logic correctly identifies relationship as essential data for a RelatedPerson resource and tracks
hasMinimumData
appropriately.packages/core/src/external/fhir/export/string/resources/medication-administration.ts (3)
10-18
: LGTM! Well-structured class implementing the interface correctly.The class follows the established pattern and properly initializes the tracking variables.
23-26
: Good tracking of minimum data for status.Correctly identifies status as essential information for a MedicationAdministration resource.
102-116
: Comprehensive dosage formatting with proper minimum data tracking.The dosage formatting logic is well-implemented, handling multiple components and correctly tracking minimum data when dosage information is present.
packages/utils/src/open-search/semantic-text-from-consolidated.ts (3)
34-38
: LGTM! Good dual-mode design with proper error handling.The script elegantly supports both file-based and API-based modes. The environment variable handling is well-structured - using
getEnvVar
to retrieve variables but deferring validation until needed in API mode.
50-68
: Excellent conditional logic structure and error handling.The dual-mode implementation is well-organized:
- Clear separation between file and API modes
- Proper error validation when required environment variables are missing
- API client instantiation only when needed (good for performance)
76-76
: Good improvement to user experience.Adding the output file path to the console log helps users locate the generated file, which is a nice UX improvement.
packages/api/src/command/medical/patient/consolidated-get.ts (1)
9-11
: Excellent refactoring to centralize consolidated data logic.Moving
getConsolidatedPatientData
andgetConsolidatedPatientDataAsync
from local implementations to the core package promotes code reuse and consistency across the platform. The import paths are correct and align with the broader refactoring effort described in the AI summary.packages/core/src/external/fhir/export/string/resources/practitioner.ts (2)
14-14
: Method signature properly updated for debug support.The method signature correctly implements the updated
FHIRResourceToString
interface, accepting an optionalisDebug
parameter and returningstring | undefined
.
17-54
: Excellent modularization with consistent formatting helpers.The refactoring successfully:
- Uses dedicated formatting functions (
formatNpiIdentifiers
,formatHumanNames
, etc.) for better maintainability- Implements consistent debug mode support with conditional labeling
- Maintains proper field separation and organization
The helper functions properly handle the
isDebug
parameter and provide consistent output formatting across FHIR resource converters.packages/core/src/external/fhir/export/string/resources/medication-dispense.ts (3)
14-16
: Good addition of minimum data tracking.The method signature is properly updated and the
hasMinimumData
tracking ensures that the method returnsundefined
when there's insufficient meaningful data, which prevents empty or meaningless string outputs.
32-40
: Excellent implementation of minimum data validation.The medication formatting correctly sets
hasMinimumData = true
when medication information is present, ensuring that medication dispense records with actual medication data are considered valid for string conversion.
130-136
: Good implementation of notes handling with minimum data tracking.The notes formatting correctly sets
hasMinimumData = true
when notes are present, and the final check ensures the method returnsundefined
when no meaningful data is available. This prevents empty medication dispense string representations.packages/api/src/routes/internal/medical/patient.ts (1)
102-115
: Verify routing hierarchy to avoid duplicate/consolidated
handlersMounting
router.use("/consolidated", patientConsolidatedRoutes)
adds a new sub-router.
If older/internal/patient/consolidated/*
handlers still exist elsewhere, requests may match multiple routes or legacy logic may become unreachable.Please ensure:
- Legacy endpoints have been removed or renamed.
- Integration tests cover the new paths.
- API documentation is updated.
No code change required, but worth double-checking before release.
packages/core/src/external/opensearch/lexical/lexical-searcher.ts (1)
60-67
: Guard against negative or non-integermaxNumberOfResults
Currently only upper/lower bounds are checked.3.14
or"5"
would pass TypeScript compile-time but could break at runtime.
AddNumber.isInteger(maxNumberOfResults)
and type narrowing to ensure a sane value.packages/core/src/external/opensearch/file/file-ingestor-direct.ts (1)
91-100
:cleanUpContents
no longer normalises quotes/newlines – verify search recall
The previous pipeline stripped quotes, newline variants and condensed multiple spaces.
The new implementation delegates toremoveHtmlTags
then only lower-cases, potentially leaving:
- Unicode quotation marks (
“
/”
)- Multiple consecutive spaces
- Line breaks if
isRemoveNewLinesAndSpaces
isfalse
This may fragment the OpenSearch term vector and hurt matching accuracy.
Consider re-adding a lightweight normalisation step:const step1 = removeHtmlTags({ contents, log, isTracing }); -const step2 = step1.toLowerCase(); -const lastStepResult = step2; +const step2 = step1.replace(regexQuotesNewlinesTabs, " "); +const step3 = step2.replace(regexMultipleSpaces, " "); +const lastStepResult = step3.toLowerCase();packages/core/src/external/fhir/export/string/resources/immunization.ts (6)
15-17
: LGTM! Clean addition of debug support and minimum data tracking.The method signature correctly adds the optional
isDebug
parameter and initializeshasMinimumData
with the default value, following the consistent pattern used across other resource converters.
19-19
: Good refactoring to parameter object pattern.The change from
formatIdentifiers(immunization.identifier)
toformatIdentifiers({ identifiers: immunization.identifier })
follows the new parameter object pattern that improves readability and consistency across formatting functions.
28-36
: Excellent implementation of debug support with minimum data tracking.The vaccine code formatting correctly:
- Uses the new parameter object pattern with
isDebug
flag- Sets
hasMinimumData = true
when meaningful data is found- Follows consistent labeling conventions
44-46
: Verify the intended behavior for primary source display.The primary source field now displays only the label "Primary Source" without showing the actual boolean value. This might be intentional for privacy/simplicity, but consider if the boolean value should be included in debug mode.
if (immunization.primarySource) { - parts.push(`Primary Source`); + parts.push(isDebug ? `Primary Source: ${immunization.primarySource}` : "Primary Source"); }
57-61
: Good update to use emptyIfDenied with minimum data tracking.The change from
checkDeny
toemptyIfDenied
aligns with the broader refactoring effort, and correctly setshasMinimumData = true
when lot number data is present.
111-112
: Proper implementation of minimum data check.The logic correctly returns
undefined
when no meaningful data is present, preventing empty or trivial string representations from being returned. This is consistent with the pattern used across other resource converters.packages/core/src/external/fhir/export/string/bundle-to-string.ts (4)
4-25
: Excellent expansion of supported FHIR resource types.The addition of Communication, Composition, Consent, Coverage, DocumentReference, FamilyMemberHistory, Location, MedicationAdministration, and RelatedPerson significantly broadens the scope of resources that can be converted to text for search and indexing purposes.
Also applies to: 30-51
53-53
: Good refinement of resource skipping logic.Changing from skipping "Patient", "Organization", and "Practitioner" to only skipping "Patient" makes sense since Organization and Practitioner resources can contain valuable searchable information.
131-131
: Good addition of debug support to bundleToString.The optional
isDebug
parameter enables consistent debug formatting across all resource types, which is valuable for troubleshooting and development.
147-154
: Excellent refactoring with proper separation of concerns.The extraction of resource conversion logic into
resourceToString
function improves:
- Code readability and maintainability
- Testability of individual components
- Separation of resource support checking from conversion logic
packages/core/src/external/fhir/export/string/resources/consent.ts (4)
1-16
: Clean imports and proper type usage.The imports are well-organized and include all necessary FHIR types and formatting utilities. Good use of specific ConsentProvision types for better type safety.
20-24
: Consistent implementation pattern.The class structure and method signature follow the established pattern from other resource converters, with proper debug support and minimum data tracking initialization.
100-120
: Well-structured verification handling.The verification mapping logic correctly handles the complex structure of ConsentVerification objects, properly filtering and joining components while maintaining debug support.
216-218
: Proper minimum data validation and return logic.The implementation correctly validates minimum data presence and returns undefined when no meaningful data is found, following the established pattern across all resource converters.
packages/core/src/command/consolidated/search/fhir-resource/search-semantic.ts (6)
2-11
: Good reorganization of imports with updated paths.The import path updates reflect a cleaner directory structure, moving from relative paths to more organized external and util directories. The imports are well-organized and include all necessary dependencies.
16-21
: Excellent enhancement of JSDoc documentation.The detailed parameter descriptions including default values and constraints (0 to 10_000 for maxNumberOfResults, 0 to 1 for similarityThreshold) significantly improve the developer experience and API clarity.
75-76
: Good use of helper function for bundle construction.Using
buildSearchSetBundle({ entries: sliced })
instead of manual bundle construction improves code maintainability and ensures consistent bundle creation across the codebase.
108-108
: Good addition of explicit return type.Adding the explicit
Promise<SearchResult[]>
return type improves type safety and makes the function signature more self-documenting.
117-117
:✅ Verification successful
Verify the class name change and its implications.
The change from
OpenSearchSemanticSearcherDirect
toOpenSearchSemanticSearcher
suggests a refactoring of the semantic search implementation. Ensure this class provides the same interface and functionality.
🏁 Script executed:
#!/bin/bash # Verify the OpenSearchSemanticSearcher class exists and has the expected search method ast-grep --pattern 'export class OpenSearchSemanticSearcher { $$$ search($$$) { $$$ } $$$ }'Length of output: 106
🏁 Script executed:
#!/bin/bash set -e echo "1. Searching for class definitions of OpenSearchSemanticSearcher:" rg -n "class OpenSearchSemanticSearcher" || echo "No class definition found." echo echo "2. Searching for any references to OpenSearchSemanticSearcher in the repo:" rg -n "OpenSearchSemanticSearcher" || echo "No references found." echo echo "3. Inspecting imports in search-semantic.ts (first 50 lines):" head -n 50 packages/core/src/command/consolidated/search/fhir-resource/search-semantic.tsLength of output: 3794
🏁 Script executed:
#!/bin/bash set -e echo "Inspecting OpenSearchSemanticSearcher class and its methods:" rg -n 'export class OpenSearchSemanticSearcher' -A 50 packages/core/src/external/opensearch/semantic/semantic-searcher.tsLength of output: 2019
✅ OpenSearchSemanticSearcher interface verified
Confirmed that the new
OpenSearchSemanticSearcher
class (packages/core/src/external/opensearch/semantic/semantic-searcher.ts) exports the same constructor signature andasync search({…}): Promise<SearchResult[]>
method as the previous implementation. No functional or interface changes detected—this refactoring is safe to merge.
41-41
:✅ Verification successful
Verify the function name change is correctly implemented.
The change from
getConsolidated
togetConsolidatedPatientData
should be verified to ensure the new function provides the same functionality and interface.
🏁 Script executed:
#!/bin/bash # Verify the new getConsolidatedPatientData function exists and has the expected signature ast-grep --pattern 'export function getConsolidatedPatientData($$$) { $$$ }'Length of output: 80
I wasn’t able to locate the new function declaration with the initial pattern—let’s search more broadly to confirm it exists and how it’s defined.
This will show both imports/usages and the actual declaration (if present). If nothing turns up, we’ll need to verify whether the function was renamed or moved and ensure it’s implemented with the same parameters and return type.
🏁 Script executed:
#!/bin/bash set -e echo "All occurrences of getConsolidatedPatientData:" rg -n "getConsolidatedPatientData" . echo echo "Explicit function/export declaration:" rg -n "export function getConsolidatedPatientData" .Length of output: 3261
🏁 Script executed:
#!/bin/bash # Show the declaration of getConsolidatedPatientData to verify its signature sed -n '80,110p' packages/core/src/command/consolidated/consolidated-get.tsLength of output: 1223
✅ Function name change verified
The exported
getConsolidatedPatientData
in
packages/core/src/command/consolidated/consolidated-get.ts
matches the expected signature and return type, and all call sites have been updated:• Declaration (lines 89–105):
export async function getConsolidatedPatientData({ patient, requestId, resources, dateFrom, dateTo, fromDashboard = false, forceDataFromFhir = false, }: GetConsolidatedPatientData): Promise<SearchSetBundle> { … }• Usages updated in both
packages/core
andpackages/api
(e.g. search-lexical.ts, search-semantic.ts, consolidated-delete.ts, routes/medical/patient.ts, etc.)No further changes required.
packages/core/src/external/fhir/export/string/resources/composition.ts (5)
1-9
: LGTM! Well-organized imports with proper grouping.The imports are cleanly organized with external dependencies first, followed by local utilities grouped by functionality.
13-17
: LGTM! Clean class declaration and method signature.The class properly implements the interface and follows TypeScript best practices with optional parameters and appropriate return types.
60-85
: LGTM! Well-structured attestation processing with good error handling.The attester mapping logic properly handles optional fields and filters out empty values. The implementation correctly follows the functional programming style preferred in the coding guidelines.
115-130
: LGTM! Excellent section processing implementation.The sections mapping logic is well-structured, properly handles nested data, and maintains consistency with the rest of the codebase. The functional approach with filter and map is exemplary.
132-135
: LGTM! Proper minimum data validation and return logic.The hasMinimumData check ensures meaningful output and the final string concatenation is appropriate.
packages/core/src/external/fhir/export/string/resources/document-reference.ts (4)
1-9
: LGTM! Consistent import organization.Imports follow the same clean pattern as the Composition class with proper grouping and naming.
61-76
: LGTM! Well-implemented relations processing.The relatesTo mapping logic properly handles complex nested structures and maintains functional programming principles. Good use of filter and map operations.
107-153
: LGTM! Excellent context processing implementation.The context processing is well-structured with proper separation of concerns, good use of arrays for building context parts, and consistent formatting. The nested structure is handled elegantly.
158-161
: LGTM! Consistent minimum data validation.Follows the same pattern as other resource converters with proper validation and return logic.
packages/core/src/external/fhir/export/string/resources/procedure.ts (4)
2-7
: LGTM! Updated imports align with interface changes.The imports have been properly updated to support the new formatting function signatures and debug functionality.
13-13
: LGTM! Method signature updated consistently.The toString method signature now matches the updated FHIRResourceToString interface with the optional isDebug parameter and appropriate return type.
16-17
: LGTM! Consistent use of new formatting function signatures.The formatting functions are properly called with named parameter objects, which improves readability and maintainability.
Also applies to: 23-27
42-47
: LGTM! Proper separation of DateTime and Period formatting.The separate handling of performedDateTime and performedPeriod is correct and maintains data integrity.
packages/core/src/command/consolidated/search/document-reference/ingest.ts (4)
1-5
: LGTM! Improved import organization with relative paths.The imports have been properly updated to use relative paths, which improves maintainability and follows the project's import conventions.
9-9
: LGTM! Simplified function signature and improved logging.The change from
fhirDoc: DocumentReferenceWithId
toentryId: string
simplifies the interface and reduces coupling. The custom logger follows the coding guidelines preference over console.log.Also applies to: 16-16
21-21
: LGTM! Consistent parameter usage and improved error messaging.All references to the parameter have been properly updated from document-focused naming to entry-focused naming, which is more accurate for the refactored function signature.
Also applies to: 29-29, 35-36
34-48
: LGTM! Proper error handling with structured logging.The error handling follows coding guidelines with structured error capture and appropriate logging. The decision not to throw errors for search ingestion failures is correctly documented and prevents disruption of main workflows.
packages/core/src/external/fhir/export/string/resources/medication-statement.ts (1)
105-106
: Double-check minimum-data semanticsAt present, minimum data is satisfied by either a medication (codeable concept or reference) or notes.
If the intention is to always require a medication, regardless of notes, remove thehasMinimumData = true
assignment when notes are present, or add an explicit boolean for “hasMedication”.
Confirm the requirement and adjust accordingly.packages/core/src/external/fhir/export/string/resources/condition.ts (1)
150-176
: Minor efficiency: avoid intermediate arrays when concatenating stage / evidence components
components.join(FIELD_SEPARATOR)
is fine for a handful of items, but you could short-circuit early if all sub-components areundefined
, saving an allocation.Not blocking—just a minor optimisation for large bundles.
packages/core/src/external/fhir/export/string/shared/telecom.ts (1)
1-51
: LGTM - Well-structured formatting utilities.The implementation follows TypeScript best practices and coding guidelines:
- Uses proper destructuring parameters
- Handles undefined cases gracefully
- Follows immutable programming patterns
- Uses meaningful function and parameter names
- Implements consistent error handling by returning undefined
The debug functionality is well-implemented and the separation of concerns between formatting multiple telecoms vs. single telecom is appropriate.
packages/api/src/routes/ehr/eclinicalworks/auth/middleware.ts (2)
14-31
: Security implementation looks solid.The
parseEClinicalWorksPracticeIdDash
function properly validates:
- Token source matches expected eClinicalWorks dash source
- Required fields (
practiceId
andpatientId
) are present- Returns appropriate data structure with external ID and query parameters
The use of
ForbiddenError
for all validation failures is appropriate for security - it prevents information leakage about what specifically failed validation.
33-45
: Middleware functions follow Express.js patterns correctly.The middleware functions properly:
- Use the correct Express.js signature
(req, res, next)
- Handle async operations with
.then(next).catch(next)
- Delegate to shared processing functions for consistency
- Pass appropriate parameters including the source identifier
This follows the coding guidelines for error handling with async operations.
packages/core/src/external/opensearch/index.ts (2)
3-11
: Well-structured configuration types.The type definitions follow TypeScript best practices:
OpenSearchConfig
provides a clean base interfaceOpenSearchConfigDirectAccess
extends appropriately with intersection types- Field names are clear and meaningful
- Types are appropriately exported
The separation between basic config and direct access config is a good design pattern.
13-25
: Generic response types improve type safety.The addition of generic
OpenSearchResponseHit<T>
andOpenSearchResponse<T>
types addresses the known issue in the OpenSearch JS client and provides better type safety. The GitHub issue reference is helpful for context.The generic approach allows for type-safe handling of different response types throughout the codebase.
packages/core/src/command/consolidated/search/document-reference/search.ts (3)
3-12
: Import path updates align with architectural refactoring.The updated import paths reflect the new "external" directory structure and are consistent with the broader codebase reorganization mentioned in the AI summary. The deeper absolute paths improve modularity and organization.
14-26
: Excellent JSDoc documentation.The comprehensive JSDoc comment clearly explains:
- Function purpose and behavior
- Parameter descriptions
- Return value specification
- Important details about content filtering scope
This improves code maintainability and follows documentation best practices.
102-112
: Local helper functions correctly implement document status logic.The helper functions properly encapsulate document status checks:
isDocStatusReady
: Correctly excludes preliminary and entered-in-error statusesisDocStatusPreliminary
: Simple, focused checkisDocStatusEnteredInError
: Simple, focused checkThis approach improves modularity by keeping the logic local to where it's used, replacing the previously imported functions.
packages/core/src/external/opensearch/shared/bulk.ts (2)
1-3
: LGTM! Clean imports and type definitions.The imports are well-organized and the type definitions follow TypeScript best practices.
70-93
: LGTM! Well-structured function with good type safety.The
resourceToBulkRequest
function is well-implemented with:
- Clear parameter destructuring
- Proper type annotations
- Good separation of concerns
- Functional approach without side effects
packages/core/src/command/consolidated/search/fhir-resource/search-consolidated-direct.ts (1)
1-21
: LGTM! Good imports and dayjs setup.The imports are well-organized and the dayjs extension is properly configured.
packages/core/src/external/fhir/export/string/resources/diagnostic-report.ts (5)
16-17
: LGTM! Good parameter addition and initialization.The addition of the optional
isDebug
parameter and the initialization ofhasMinimumData
withdefaultHasMinimumData
follows good practices.
120-127
: LGTM! Good implementation with proper data validation.The
presentedFormsToText
integration is well-implemented with:
- Proper iteration through forms
- Debug-aware labeling
- Minimum data tracking
- Use of the
singleLine
helper function
153-153
: LGTM! Proper minimum data validation.The return of
undefined
when there's insufficient meaningful data follows the established pattern and prevents empty or meaningless output.
159-161
: LGTM! Simple and effective helper function.The
singleLine
helper function is well-implemented:
- Single responsibility
- Immutable (doesn't modify input)
- Simple and readable
20-21
:⚠️ Potential issueFix parameter structure for formatIdentifiers.
The
formatIdentifiers
function expects an object with anidentifiers
property, but you're passing the identifiers directly.- const identifierStr = formatIdentifiers({ identifiers: report.identifier }); + const identifierStr = formatIdentifiers({ identifiers: report.identifier });Wait, looking at the relevant code snippet, the function signature is correct. The current implementation matches the expected signature from the relevant snippet. Let me reconsider...
Actually, the code is correct as written. The function expects
{ identifiers: Identifier[] | undefined }
and that's exactly what's being passed.Likely an incorrect or invalid review comment.
packages/core/src/external/fhir/export/string/shared/identifier.ts (3)
5-19
: LGTM! Well-structured identifier formatting function.The implementation correctly handles edge cases, uses appropriate functional programming patterns with
flatMap
, and provides proper deduplication. The type safety and early return patterns follow the coding guidelines well.
30-44
: LGTM! Robust single identifier formatting.The function properly handles validation, trimming, and system filtering. The use of
some()
withincludes()
for partial system matching is appropriate and follows functional programming principles.
52-58
: LGTM! Useful convenience function for NPI filtering.This helper function provides a clean interface for the common use case of filtering NPI identifiers, following the DRY principle by reusing the core
formatIdentifiers
function.packages/core/src/external/fhir/export/string/shared/address.ts (2)
11-27
: LGTM! Well-refactored function with improved API design.The refactoring to use object parameters enhances readability and maintainability. The debug support and consistent return patterns align well with the broader FHIR formatting utilities.
29-50
: LGTM! Clean address formatting implementation.The function properly handles address component extraction and filtering. The decision to exclude country (line 44) and the separate handling of the text field (line 48) are reasonable design choices.
packages/core/src/external/fhir/export/string/resources/allergy-intolerance.ts (2)
13-119
: LGTM! Consistent debug support implementation.The
toString
method is properly updated to support debug mode with consistent parameter passing to all formatting helpers. ThehasMinimumData
tracking ensures meaningful output validation.
121-139
: LGTM! Well-structured helper function for reaction formatting.The function properly modularizes reaction formatting logic and maintains consistency with the debug parameter pattern used throughout the codebase.
packages/api/src/routes/internal/medical/patient-consolidated.ts (2)
153-175
: LGTM! Clean ingestion route implementation.The route properly validates parameters and handles the ingestion process. The fallback to all patients when no IDs are provided (lines 162-166) is a useful feature.
Note that the sequential processing approach aligns with the comment about this being designed for small patient volumes, with larger volumes requiring a queue-based architecture.
1-32
: LGTM! Well-organized imports and setup.The imports are properly structured and follow the coding guidelines. The dayjs plugin extension (line 30) follows the recommended pattern for date handling.
packages/core/src/external/fhir/export/string/shared/codeable-concept.ts (1)
18-28
: LGTM: Good use of options object pattern.The refactoring from positional parameters to an options object improves maintainability and follows TypeScript best practices. The destructuring with defaults is well implemented.
packages/core/src/external/fhir/export/string/shared/coding.ts (1)
6-6
:✅ Verification successful
Clarify the internal code system pattern.
The
INTERNAL_CODE_SYSTEM
constant ends with a dot, which might be incomplete. Please verify this is the correct pattern for identifying internal codes.
🏁 Script executed:
#!/bin/bash # Description: Search for other usages of internal code system patterns to verify correctness # Expected: Find other references to internal OID patterns or similar filtering logic rg -A 3 -B 3 "urn:oid:1\.2\.840" --type tsLength of output: 4717
INTERNAL_CODE_SYSTEM prefix is correct.
The search confirms that FHIR codings use full OIDs like
"urn:oid:1.2.840.114350…"
in tests, so the trailing dot on"urn:oid:1.2.840."
is intentional to match that prefix. No changes required.packages/api/src/external/ehr/eclinicalworks/command/sync-patient.ts (1)
67-71
: LGTM: Good async error handling pattern.The use of
.catch(processAsyncError(...))
for fire-and-forget async operations follows the coding guidelines correctly.packages/core/src/external/ehr/eclinicalworks/index.ts (2)
35-39
: LGTM: Good factory pattern implementation.The static factory method with async initialization follows best practices for async object creation.
70-99
: LGTM: Good delegation pattern.The private
makeRequest
method properly delegates to the shared utility while providing the necessary context and configuration.
@@ -60,7 +60,7 @@ export async function handler(event: SQSEvent) { | |||
} | |||
const openSearch = new OpenSearchFileIngestorDirect({ | |||
region, | |||
endpoint: "https://" + host, | |||
endpoint: host, |
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.
💡 Verification agent
🧩 Analysis chain
Verify endpoint URL handling in the refactored modules.
The change from concatenating "https://" + host
to passing host
directly suggests the endpoint URL handling has been moved into the OpenSearchFileIngestorDirect
constructor or related modules. Please ensure this change is consistent with how other OpenSearch modules handle endpoints.
🏁 Script executed:
#!/bin/bash
# Description: Verify endpoint handling in OpenSearch file ingestor modules
# Expected: Find how endpoint URLs are constructed in the new file structure
# Search for endpoint handling in OpenSearch file modules
ast-grep --pattern 'endpoint: $_'
# Check how OpenSearchFileIngestorDirect handles endpoint parameter
ast-grep --pattern 'class OpenSearchFileIngestorDirect {
$$$
constructor($_) {
$$$
}
$$$
}'
# Look for "https://" prefix handling
rg -A 3 -B 3 "https://"
Length of output: 85649
🏁 Script executed:
#!/bin/bash
set -e
echo "=== 1. Imports and usage in sqs-to-opensearch-xml.ts ==="
grep -n "import.*Ingestor" -n packages/lambdas/src/sqs-to-opensearch-xml.ts || true
grep -n "new .*Ingestor" packages/lambdas/src/sqs-to-opensearch-xml.ts || true
echo
echo "=== 2. Locate Ingestor class definitions ==="
rg -n "class .*Ingestor" -n .
echo
echo "=== 3. Show constructor bodies for found Ingestor classes ==="
for file in $(rg -l "class .*Ingestor" --max-count 5 .); do
echo "---- File: $file ----"
# Print the class definition and constructor
sed -n '/class .*Ingestor/,/^\}/p' "$file" | sed -n '/constructor/,/^\}/p'
done
Length of output: 15700
🏁 Script executed:
#!/bin/bash
set -e
echo "=== sqs-to-opensearch-xml.ts (first 200 lines) ==="
sed -n '1,200p' packages/lambdas/src/sqs-to-opensearch-xml.ts
echo
echo "=== Environment variable references ==="
grep -Rn "process.env" -n packages/lambdas/src/sqs-to-opensearch-xml.ts || true
Length of output: 5445
Ensure full URL is passed to OpenSearchFileIngestorDirect
The OpenSearchFileIngestorDirect
constructor does not add a protocol prefix, it uses whatever you pass as endpoint
directly in the Elasticsearch client. Previously you were doing "https://" + host
in the Lambda, but now passing host
alone means the client may receive an invalid URL if SEARCH_HOST
doesn’t include http(s)://
.
• packages/lambdas/src/sqs-to-opensearch-xml.ts (around line 61):
- Confirm your
SEARCH_HOST
env var includes the protocol, e.g.https://my-domain.es.amazonaws.com
- Or add a fallback in code, for example:
const openSearch = new OpenSearchFileIngestorDirect({ region, endpoint: host.startsWith("http") ? host : `https://${host}`, indexName, username, password, });
This will restore the previous behavior and prevent client errors if someone sets SEARCH_HOST
without the protocol.
🤖 Prompt for AI Agents
In packages/lambdas/src/sqs-to-opensearch-xml.ts at line 63, the endpoint is
passed as host without the "https://" prefix, but OpenSearchFileIngestorDirect
expects a full URL including the protocol. Fix this by checking if host starts
with "http" and if not, prepend "https://" before passing it as the endpoint.
This ensures the client receives a valid URL regardless of how SEARCH_HOST is
set in the environment.
router.post( | ||
"/:id", | ||
handleParams, | ||
requestLogger, | ||
asyncHandler(async (req: Request, res: Response) => { | ||
const cxId = getCxIdOrFail(req); | ||
const eclinicalworksPatientId = getFrom("params").orFail("id", req); | ||
const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req); | ||
const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req); | ||
const patientId = await syncEClinicalWorksPatientIntoMetriport({ | ||
cxId, | ||
eclinicalworksPracticeId, | ||
eclinicalworksPatientId, | ||
eclinicalworksTokenId, | ||
}); | ||
return res.status(httpStatus.OK).json(patientId); | ||
}) | ||
); |
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.
🛠️ Refactor suggestion
Remove duplicate POST route implementation.
This POST route is identical to the GET route above, creating unnecessary code duplication. If both HTTP methods are intentionally supported, they should share the same handler function.
After implementing the shared handler from the previous comment:
router.post(
"/:id",
handleParams,
requestLogger,
- asyncHandler(async (req: Request, res: Response) => {
- const cxId = getCxIdOrFail(req);
- const eclinicalworksPatientId = getFrom("params").orFail("id", req);
- const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req);
- const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req);
- const patientId = await syncEClinicalWorksPatientIntoMetriport({
- cxId,
- eclinicalworksPracticeId,
- eclinicalworksPatientId,
- eclinicalworksTokenId,
- });
- return res.status(httpStatus.OK).json(patientId);
- })
+ handlePatientSync
);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
router.post( | |
"/:id", | |
handleParams, | |
requestLogger, | |
asyncHandler(async (req: Request, res: Response) => { | |
const cxId = getCxIdOrFail(req); | |
const eclinicalworksPatientId = getFrom("params").orFail("id", req); | |
const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req); | |
const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req); | |
const patientId = await syncEClinicalWorksPatientIntoMetriport({ | |
cxId, | |
eclinicalworksPracticeId, | |
eclinicalworksPatientId, | |
eclinicalworksTokenId, | |
}); | |
return res.status(httpStatus.OK).json(patientId); | |
}) | |
); | |
router.post( | |
"/:id", | |
handleParams, | |
requestLogger, | |
handlePatientSync | |
); |
🤖 Prompt for AI Agents
In packages/api/src/routes/ehr/eclinicalworks/patient.ts around lines 48 to 65,
there is a duplicate POST route implementation identical to the GET route above.
To fix this, extract the async handler function into a separate named function
and reuse it for both the POST and GET routes. This will remove code duplication
and ensure both routes share the same logic.
router.get( | ||
"/:id", | ||
handleParams, | ||
requestLogger, | ||
asyncHandler(async (req: Request, res: Response) => { | ||
const cxId = getCxIdOrFail(req); | ||
const eclinicalworksPatientId = getFrom("params").orFail("id", req); | ||
const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req); | ||
const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req); | ||
const patientId = await syncEClinicalWorksPatientIntoMetriport({ | ||
cxId, | ||
eclinicalworksPracticeId, | ||
eclinicalworksPatientId, | ||
eclinicalworksTokenId, | ||
}); | ||
return res.status(httpStatus.OK).json(patientId); | ||
}) | ||
); |
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.
🛠️ Refactor suggestion
Consider consolidating duplicate route logic.
The GET route implementation looks correct, but there's significant code duplication between the GET and POST routes (lines 20-37 and 48-65). This violates the DRY principle mentioned in the coding guidelines.
Consider extracting the common logic into a shared function:
+const handlePatientSync = asyncHandler(async (req: Request, res: Response) => {
+ const cxId = getCxIdOrFail(req);
+ const eclinicalworksPatientId = getFrom("params").orFail("id", req);
+ const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req);
+ const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req);
+ const patientId = await syncEClinicalWorksPatientIntoMetriport({
+ cxId,
+ eclinicalworksPracticeId,
+ eclinicalworksPatientId,
+ eclinicalworksTokenId,
+ });
+ return res.status(httpStatus.OK).json({ patientId });
+});
router.get(
"/:id",
handleParams,
requestLogger,
- asyncHandler(async (req: Request, res: Response) => {
- const cxId = getCxIdOrFail(req);
- const eclinicalworksPatientId = getFrom("params").orFail("id", req);
- const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req);
- const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req);
- const patientId = await syncEClinicalWorksPatientIntoMetriport({
- cxId,
- eclinicalworksPracticeId,
- eclinicalworksPatientId,
- eclinicalworksTokenId,
- });
- return res.status(httpStatus.OK).json(patientId);
- })
+ handlePatientSync
);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
router.get( | |
"/:id", | |
handleParams, | |
requestLogger, | |
asyncHandler(async (req: Request, res: Response) => { | |
const cxId = getCxIdOrFail(req); | |
const eclinicalworksPatientId = getFrom("params").orFail("id", req); | |
const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req); | |
const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req); | |
const patientId = await syncEClinicalWorksPatientIntoMetriport({ | |
cxId, | |
eclinicalworksPracticeId, | |
eclinicalworksPatientId, | |
eclinicalworksTokenId, | |
}); | |
return res.status(httpStatus.OK).json(patientId); | |
}) | |
); | |
// Extract and reuse the shared handler for both GET and POST routes | |
const handlePatientSync = asyncHandler(async (req: Request, res: Response) => { | |
const cxId = getCxIdOrFail(req); | |
const eclinicalworksPatientId = getFrom("params").orFail("id", req); | |
const eclinicalworksPracticeId = getFromQueryOrFail("practiceId", req); | |
const eclinicalworksTokenId = getFromQueryOrFail("tokenId", req); | |
const patientId = await syncEClinicalWorksPatientIntoMetriport({ | |
cxId, | |
eclinicalworksPracticeId, | |
eclinicalworksPatientId, | |
eclinicalworksTokenId, | |
}); | |
// Return a structured response | |
return res.status(httpStatus.OK).json({ patientId }); | |
}); | |
// GET route | |
router.get( | |
"/:id", | |
handleParams, | |
requestLogger, | |
handlePatientSync | |
); |
🤖 Prompt for AI Agents
In packages/api/src/routes/ehr/eclinicalworks/patient.ts around lines 20 to 37,
the GET and POST routes contain duplicated logic for extracting parameters and
calling syncEClinicalWorksPatientIntoMetriport. To fix this, extract the shared
logic into a separate async function that accepts the request object, performs
the parameter extraction and patient sync, and returns the patientId. Then,
update both the GET and POST route handlers to call this new function and return
its result, eliminating duplication and adhering to the DRY principle.
export function processAsyncError( | ||
msg: string, | ||
log?: typeof console.log | undefined, | ||
useMsgAsTitle = false | ||
) { |
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.
🛠️ Refactor suggestion
Improve parameter handling to avoid non-null assertion.
The log
parameter is typed as optional but then requires a non-null assertion operator on line 64. Consider making it required or handle the undefined case properly.
Apply this diff to improve the parameter handling:
-export function processAsyncError(
- msg: string,
- log?: typeof console.log | undefined,
- useMsgAsTitle = false
-) {
- if (!log) log = out().log;
+export function processAsyncError(
+ msg: string,
+ log: typeof console.log = out().log,
+ useMsgAsTitle = false
+) {
🤖 Prompt for AI Agents
In packages/core/src/util/error/shared.ts around lines 56 to 60, the optional
parameter 'log' is used with a non-null assertion later, which is unsafe. To fix
this, either make the 'log' parameter required by removing the optional modifier
or add a check to handle the case when 'log' is undefined before using it,
ensuring no non-null assertion is needed.
it("should handle undefined values in repeat rules", () => { | ||
const timing: Timing = { | ||
repeat: { | ||
frequency: undefined as unknown as number, | ||
period: undefined as unknown as number, | ||
periodUnit: undefined as unknown as "s" | "min" | "h" | "d" | "wk" | "mo" | "a", | ||
}, | ||
}; | ||
expect(formatTiming({ timing })).toBeUndefined(); | ||
}); |
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.
🛠️ Refactor suggestion
Improve type safety in test.
The use of as unknown as
type assertions to force undefined values should be avoided as it bypasses TypeScript's type safety.
Consider testing with a more realistic scenario or using a different approach:
- const timing: Timing = {
- repeat: {
- frequency: undefined as unknown as number,
- period: undefined as unknown as number,
- periodUnit: undefined as unknown as "s" | "min" | "h" | "d" | "wk" | "mo" | "a",
- },
- };
+ const timing: Timing = {
+ repeat: {},
+ };
🤖 Prompt for AI Agents
In packages/core/src/external/fhir/export/string/shared/__tests__/timing.test.ts
around lines 176 to 185, the test uses unsafe type assertions with 'as unknown
as' to assign undefined to typed properties, which bypasses TypeScript's type
safety. To fix this, remove the forced type assertions and instead test with
either optional properties omitted or assign values that are valid but represent
absence or edge cases according to the Timing type definition, ensuring the test
remains type-safe and realistic.
export function formatCoding({ | ||
coding, | ||
skipInternalCodes, | ||
}: { | ||
coding: Coding | undefined; | ||
skipInternalCodes?: boolean | undefined; | ||
}): string | undefined { | ||
if (!coding) return undefined; | ||
if (skipInternalCodes && isInternalCoding(coding)) return undefined; | ||
|
||
const system = isAllowedSystem(coding.system); | ||
if (!system) return undefined; | ||
const code = getCode({ coding, skipInternalCodes }); | ||
const displayPre = emptyIfDenied(coding.display); | ||
const display = displayPre ? displayPre.trim() : undefined; | ||
|
||
if (code) return codeAndDisplayToString(code, display); | ||
|
||
const altCode = ""; | ||
const codeAndDisplay = codeAndDisplayToString(altCode, coding.display); | ||
if (!codeAndDisplay) return undefined; | ||
|
||
return codeAndDisplay; | ||
} |
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.
🛠️ Refactor suggestion
Simplify function logic and improve readability.
The function has redundant logic and could be simplified for better maintainability.
export function formatCoding({
coding,
skipInternalCodes,
}: {
coding: Coding | undefined;
skipInternalCodes?: boolean | undefined;
}): string | undefined {
if (!coding) return undefined;
if (skipInternalCodes && isInternalCoding(coding)) return undefined;
const system = isAllowedSystem(coding.system);
if (!system) return undefined;
const code = getCode({ coding, skipInternalCodes });
const displayPre = emptyIfDenied(coding.display);
const display = displayPre ? displayPre.tri
F438
m() : undefined;
- if (code) return codeAndDisplayToString(code, display);
-
- const altCode = "";
- const codeAndDisplay = codeAndDisplayToString(altCode, coding.display);
- if (!codeAndDisplay) return undefined;
-
- return codeAndDisplay;
+ return codeAndDisplayToString(code, display);
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
export function formatCoding({ | |
coding, | |
skipInternalCodes, | |
}: { | |
coding: Coding | undefined; | |
skipInternalCodes?: boolean | undefined; | |
}): string | undefined { | |
if (!coding) return undefined; | |
if (skipInternalCodes && isInternalCoding(coding)) return undefined; | |
const system = isAllowedSystem(coding.system); | |
if (!system) return undefined; | |
const code = getCode({ coding, skipInternalCodes }); | |
const displayPre = emptyIfDenied(coding.display); | |
const display = displayPre ? displayPre.trim() : undefined; | |
if (code) return codeAndDisplayToString(code, display); | |
const altCode = ""; | |
const codeAndDisplay = codeAndDisplayToString(altCode, coding.display); | |
if (!codeAndDisplay) return undefined; | |
return codeAndDisplay; | |
} | |
export function formatCoding({ | |
coding, | |
skipInternalCodes, | |
}: { | |
coding: Coding | undefined; | |
skipInternalCodes?: boolean | undefined; | |
}): string | undefined { | |
if (!coding) return undefined; | |
if (skipInternalCodes && isInternalCoding(coding)) return undefined; | |
const system = isAllowedSystem(coding.system); | |
if (!system) return undefined; | |
const code = getCode({ coding, skipInternalCodes }); | |
const displayPre = emptyIfDenied(coding.display); | |
const display = displayPre ? displayPre.trim() : undefined; | |
return codeAndDisplayToString(code, display); | |
} |
🤖 Prompt for AI Agents
In packages/core/src/external/fhir/export/string/shared/coding.ts between lines
42 and 65, the formatCoding function contains redundant checks and variable
assignments that can be streamlined. Simplify by removing unnecessary variables
like altCode and directly returning results where possible, consolidating
conditional returns, and trimming the display value once to improve readability
and maintainability without changing the function's behavior.
export async function syncEClinicalWorksPatientIntoMetriport({ | ||
cxId, | ||
eclinicalworksPracticeId, | ||
eclinicalworksPatientId, | ||
eclinicalworksTokenId, | ||
api, | ||
triggerDq = false, | ||
}: SyncEClinicalWorksPatientIntoMetriportParams): Promise<string> { | ||
const existingPatient = await getPatientMapping({ | ||
cxId, | ||
externalId: eclinicalworksPatientId, | ||
source: EhrSources.eclinicalworks, | ||
}); | ||
if (existingPatient) { | ||
const metriportPatient = await getPatientOrFail({ | ||
cxId, | ||
id: existingPatient.patientId, | ||
}); | ||
const metriportPatientId = metriportPatient.id; | ||
return metriportPatientId; | ||
} | ||
|
||
const eclinicalworksApi = | ||
api ?? | ||
(await createEClinicalWorksClientFromTokenId({ | ||
cxId, | ||
practiceId: eclinicalworksPracticeId, | ||
tokenId: eclinicalworksTokenId, | ||
})); | ||
const eclinicalworksPatient = await eclinicalworksApi.getPatient({ | ||
cxId, | ||
patientId: eclinicalworksPatientId, | ||
}); | ||
const possibleDemographics = createMetriportPatientDemosFhir(eclinicalworksPatient); | ||
const metriportPatient = await getOrCreateMetriportPatientFhir({ | ||
cxId, | ||
source: EhrSources.eclinicalworks, | ||
practiceId: eclinicalworksPracticeId, | ||
possibleDemographics, | ||
externalId: eclinicalworksPatientId, | ||
}); | ||
if (triggerDq) { | ||
queryDocumentsAcrossHIEs({ | ||
cxId, | ||
patientId: metriportPatient.id, | ||
}).catch(processAsyncError(`EClinicalWorks queryDocumentsAcrossHIEs`)); | ||
} | ||
await findOrCreatePatientMapping({ | ||
cxId, | ||
patientId: metriportPatient.id, | ||
externalId: eclinicalworksPatientId, | ||
source: EhrSources.eclinicalworks, | ||
}); | ||
return metriportPatient.id; | ||
} |
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.
🛠️ Refactor suggestion
Consider decomposing the main function for better maintainability.
The syncEClinicalWorksPatientIntoMetriport
function handles multiple responsibilities. Consider breaking it down into smaller, focused functions.
+async function handleExistingPatient(
+ cxId: string,
+ externalId: string
+): Promise<string | null> {
+ const existingPatient = await getPatientMapping({
+ cxId,
+ externalId,
+ source: EhrSources.eclinicalworks,
+ });
+ if (existingPatient) {
+ const metriportPatient = await getPatientOrFail({
+ cxId,
+ id: existingPatient.patientId,
+ });
+ return metriportPatient.id;
+ }
+ return null;
+}
+
+async function createAndSyncNewPatient(
+ params: SyncEClinicalWorksPatientIntoMetriportParams
+): Promise<string> {
+ const {
+ cxId,
+ eclinicalworksPracticeId,
+ eclinicalworksPatientId,
+ eclinicalworksTokenId,
+ api,
+ triggerDq = false,
+ } = params;
+
+ const eclinicalworksApi =
+ api ??
+ (await createEClinicalWorksClientFromTokenId({
+ cxId,
+ practiceId: eclinicalworksPracticeId,
+ tokenId: eclinicalworksTokenId,
+ }));
+
+ // ... rest of the logic
+}
+
export async function syncEClinicalWorksPatientIntoMetriport({
cxId,
eclinicalworksPracticeId,
eclinicalworksPatientId,
eclinicalworksTokenId,
api,
triggerDq = false,
}: SyncEClinicalWorksPatientIntoMetriportParams): Promise<string> {
- const existingPatient = await getPatientMapping({
- cxId,
- externalId: eclinicalworksPatientId,
- source: EhrSources.eclinicalworks,
- });
- if (existingPatient) {
- const metriportPatient = await getPatientOrFail({
- cxId,
- id: existingPatient.patientId,
- });
10000
- const metriportPatientId = metriportPatient.id;
- return metriportPatientId;
- }
+ const existingPatientId = await handleExistingPatient(cxId, eclinicalworksPatientId);
+ if (existingPatientId) {
+ return existingPatientId;
+ }
+
+ return await createAndSyncNewPatient({
+ cxId,
+ eclinicalworksPracticeId,
+ eclinicalworksPatientId,
+ eclinicalworksTokenId,
+ api,
+ triggerDq,
+ });
}
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In packages/api/src/external/ehr/eclinicalworks/command/sync-patient.ts between
lines 25 and 79, the syncEClinicalWorksPatientIntoMetriport function is doing
too many tasks such as checking existing patients, creating API clients,
fetching patient data, and triggering data queries. Refactor by extracting these
distinct responsibilities into smaller helper functions like
checkExistingPatientMapping, fetchEClinicalWorksPatientData,
createOrUpdateMetriportPatient, and triggerDataQualityChecks. Then call these
helpers from the main function to improve readability and maintainability.
async getPatient({ cxId, patientId }: { cxId: string; patientId: string }): Promise<Patient> { | ||
const { debug } = out( | ||
`EClinicalWorks getPatient - cxId ${cxId} practiceId ${this.practiceId} patientId ${patientId}` | ||
); | ||
const patientUrl = `/Patient/${patientId}`; | ||
const additionalInfo = { cxId, practiceId: this.practiceId, patientId }; | ||
const patient = await this.makeRequest<Patient>({ | ||
cxId, | ||
patientId, | ||
s3Path: "patient", | ||
method: "GET", | ||
url: patientUrl, | ||
schema: patientSchema, | ||
additionalInfo, | ||
debug, | ||
}); | ||
return patient; | ||
} |
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.
🛠️ Refactor suggestion
Consider adding error handling for API calls.
The getPatient
method doesn't handle potential errors from the API call. Consider adding try-catch for better error handling and logging.
async getPatient({ cxId, patientId }: { cxId: string; patientId: string }): Promise<Patient> {
const { debug } = out(
`EClinicalWorks getPatient - cxId ${cxId} practiceId ${this.practiceId} patientId ${patientId}`
);
const patientUrl = `/Patient/${patientId}`;
const additionalInfo = { cxId, practiceId: this.practiceId, patientId };
- const patient = await this.makeRequest<Patient>({
- cxId,
- patientId,
- s3Path: "patient",
- method: "GET",
- url: patientUrl,
- schema: patientSchema,
- additionalInfo,
- debug,
- });
- return patient;
+ try {
+ const patient = await this.makeRequest<Patient>({
+ cxId,
+ patientId,
+ s3Path: "patient",
+ method: "GET",
+ url: patientUrl,
+ schema: patientSchema,
+ additionalInfo,
+ debug,
+ });
+ return patient;
+ } catch (error) {
+ debug(`Failed to get patient: ${error}`);
+ throw error;
+ }
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
async getPatient({ cxId, patientId }: { cxId: string; patientId: string }): Promise<Patient> { | |
const { debug } = out( | |
`EClinicalWorks getPatient - cxId ${cxId} practiceId ${this.practiceId} patientId ${patientId}` | |
); | |
const patientUrl = `/Patient/${patientId}`; | |
const additionalInfo = { cxId, practiceId: this.practiceId, patientId }; | |
const patient = await this.makeRequest<Patient>({ | |
cxId, | |
patientId, | |
s3Path: "patient", | |
method: "GET", | |
url: patientUrl, | |
schema: patientSchema, | |
additionalInfo, | |
debug, | |
}); | |
return patient; | |
} | |
async getPatient({ cxId, patientId }: { cxId: string; patientId: string }): Promise<Patient> { | |
const { debug } = out( | |
`EClinicalWorks getPatient - cxId ${cxId} practiceId ${this.practiceId} patientId ${patientId}` | |
); | |
const patientUrl = `/Patient/${patientId}`; | |
const additionalInfo = { cxId, practiceId: this.practiceId, patientId }; | |
try { | |
const patient = await this.makeRequest<Patient>({ | |
cxId, | |
patientId, | |
s3Path: "patient", | |
method: "GET", | |
url: patientUrl, | |
schema: patientSchema, | |
additionalInfo, | |
debug, | |
}); | |
return patient; | |
} catch (error) { | |
debug(`Failed to get patient: ${error}`); | |
throw error; | |
} | |
} |
🤖 Prompt for AI Agents
In packages/core/src/external/ehr/eclinicalworks/index.ts around lines 51 to 68,
the getPatient method lacks error handling for the API call. Wrap the await
this.makeRequest call inside a try-catch block, catch any errors thrown during
the request, log the error with relevant context including cxId and patientId,
and rethrow or handle the error appropriately to ensure failures are managed
gracefully.
headers: { | ||
Authorization: `Bearer ${this.token}`, | ||
"Content-Type": "application/x-www-form-urlencoded", | ||
}, | ||
}); |
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.
💡 Verification agent
🧩 Analysis chain
Reconsider hard-coded Content-Type header.
The Content-Type is set to "application/x-www-form-urlencoded" but this might not be appropriate for all API calls, especially FHIR endpoints which typically use "application/fhir+json".
🌐 Web query:
What Content-Type headers does EClinicalWorks FHIR API expect for different operations?
💡 Result:
Content-Type Headers Expected by eClinicalWorks FHIR API
eClinicalWorks FHIR API adheres to the general FHIR standard for HTTP headers and MIME types. Although official eClinicalWorks documentation on this particular header is limited in the provided search results, typical FHIR API expectations, referenced by multiple sources, apply to their endpoints.
Standard FHIR Content-Type Headers
Depending on the type of operation (fetching data, sending new resources, updating records), the following Content-Type
headers are used:
-
Reading Data (GET requests):
- Header:
Accept: application/fhir+json
(orapplication/fhir+xml
if XML is required) - This specifies the expected format for the response. JSON is the most common format in contemporary implementations[2][5].
- Header:
-
Creating or Updating Data (POST/PUT requests):
- Header:
Content-Type: application/fhir+json
- This indicates the format being sent in the request body. JSON is the preferred format, following the modern FHIR API conventions[2][5][9].
- Header:
-
Partial Updates (PATCH requests):
- Header:
Content-Type: application/json-patch+json
orapplication/fhir+json
- Though PATCH is less frequently used, partial resource modifications may require
application/json-patch+json
as per the FHIR specification[3].
- Header:
Table: Common FHIR Operations and Headers
Operation | HTTP Method | Content-Type (Request) | Accept (Response) |
---|---|---|---|
Read (e.g., retrieve patient) | GET | – | application/fhir+json |
Create (e.g., add patient) | POST | application/fhir+json | application/fhir+json |
Update (replace resource) | PUT | application/fhir+json | application/fhir+json |
Patch (partial update) | PATCH | application/json-patch+json | application/fhir+json |
Delete | DELETE | – | – |
- For read and delete operations, a
Content-Type
header is typically not necessary, though theAccep 10000 t
header determines the response format[2][5][9].
eClinicalWorks-Specific Integration Guidance
- eClinicalWorks uses RESTful FHIR APIs, and integrations are expected to comply with standard FHIR headers when making requests to their endpoints[6][10].
- The default and preferred format is JSON, i.e.,
application/fhir+json
[2][9]. - Authorization is handled separately and generally requires an
Authorization
header with a Bearer token.
Default Encoding and Fallback Behavior
If the Accept
or Content-Type
headers are not specified:
- Most FHIR servers, including implementations like eClinicalWorks, default to returning and processing
application/fhir+json
[5]. - If both
Accept
and_format
are provided,_format
takes precedence[5].
Summary
For all practical operations with the eClinicalWorks FHIR API:
- Use
Content-Type: application/fhir+json
for all POST and PUT requests. - Use
Accept: application/fhir+json
to specify response format, especially in GET requests. - For PATCH, use
Content-Type: application/json-patch+json
as needed. - Always include an
Authorization
header per API requirements[2][5][9].
These expectations follow the standard FHIR conventions and are supported by eClinicalWorks in their integration offerings.
Citations:
- 1: https://www.eclinicalworks.com/blog/whats-fhir-and-how-will-it-drive-healthcare-interoperability/
- 2: https://www.clindcast.com/fhir-apis-a-step-by-step-guide-for-beginners/
- 3: https://build.fhir.org/http.html
- 4: https://blog.eclinicalworks.com/topic/fhir-api
- 5: https://nhsconnect.github.io/FHIR-SpineCore/resources_headers.html
- 6: https://softwarefinder.com/resources/how-to-integrate-eclinicalworks-ehr-with-other-systems
- 7: https://www.youtube.com/watch?v=57YVixIYbTk
- 8: https://hapifhir.io/hapi-fhir/docs/server_plain/rest_operations.html
- 9: https://www.calmhsa.org/wp-content/uploads/2024/04/FHIR-API-Documentation-v3.pdf
- 10: https://www.clarity-ventures.com/articles/eclinicalworks-ehr-emr-integrations-with-fhir-healow-endpoints
🏁 Script executed:
#!/bin/bash
# Search for Content-Type occurrences in the file
rg '"Content-Type"' -n packages/core/src/external/ehr/eclinicalworks/index.ts || true
# Display the file contents around the OAuth/token request to understand context
sed -n '1,200p' packages/core/src/external/ehr/eclinicalworks/index.ts
Length of output: 3160
Update default FHIR Content-Type header
The hard-coded "application/x-www-form-urlencoded"
in your FHIR client initialization will break JSON-based FHIR operations. Instead, remove or override the default and set headers per operation:
• File: packages/core/src/external/ehr/eclinicalworks/index.ts
– In initialize()
, replace the default headers block:
- this.axiosFhirInstance = axios.create({
- baseURL: `${this.baseFhirUrl}/fhir/r4/${this.practiceId}`,
- headers: {
- Authorization: `Bearer ${this.token}`,
- "Content-Type": "application/x-www-form-urlencoded",
- },
- });
+ this.axiosFhirInstance = axios.create({
+ baseURL: `${this.baseFhirUrl}/fhir/r4/${this.practiceId}`,
+ headers: {
+ Authorization: `Bearer ${this.token}`,
+ // Default Accept for all GET/DELETE
+ Accept: "application/fhir+json",
+ },
+});
• In each request that sends or patches data, override Content-Type
appropriately:
- POST/PUT →
"application/fhir+json"
- PATCH →
"application/json-patch+json"
For example, inside makeRequest
:
await makeRequest<T>({
…,
headers: {
"Content-Type": "application/fhir+json",
…headers,
},
…
});
This ensures GET/DELETE use Accept: application/fhir+json
and write operations send the correct FHIR JSON payload.
🤖 Prompt for AI Agents
In packages/core/src/external/ehr/eclinicalworks/index.ts around lines 44 to 48,
the Content-Type header is hard-coded to "application/x-www-form-urlencoded",
which is incorrect for FHIR JSON operations. Remove this default header from
initialization and instead set Content-Type dynamically per request: use
"application/fhir+json" for POST and PUT requests, "application/json-patch+json"
for PATCH requests, and omit Content-Type for GET and DELETE while setting
Accept to "application/fhir+json". Update the makeRequest calls to include these
headers accordingly to comply with FHIR API standards.
const response = await client.index( | ||
{ | ||
index: indexName, | ||
id: entryId, | ||
body: { doc: document, doc_as_upsert: true }, | ||
}, | ||
{ requestTimeout: DEFAULT_INGESTION_TIMEOUT } | ||
); |
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.
Incorrect API used – upsert will silently fail
client.index()
does not understand the doc
/ doc_as_upsert
syntax; that belongs to the update
API.
The current call will create a document containing the fields doc
and doc_as_upsert
instead of performing an upsert, breaking idempotency and update semantics.
- const response = await client.index(
+ const response = await client.update(
{
index: indexName,
id: entryId,
body: { doc: document, doc_as_upsert: true },
},
{ requestTimeout: DEFAULT_INGESTION_TIMEOUT }
);
Please switch to client.update()
(or remove the wrapper and use client.index()
with the full source) and add a regression test – otherwise later updates will be silently ignored.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const response = await client.index( | |
{ | |
index: indexName, | |
id: entryId, | |
body: { doc: document, doc_as_upsert: true }, | |
}, | |
{ requestTimeout: DEFAULT_INGESTION_TIMEOUT } | |
); | |
const response = await client.update( | |
{ | |
index: indexName, | |
id: entryId, | |
body: { doc: document, doc_as_upsert: true }, | |
}, | |
{ requestTimeout: DEFAULT_INGESTION_TIMEOUT } | |
); |
🤖 Prompt for AI Agents
In packages/core/src/external/opensearch/text-ingestor.ts around lines 101 to
108, the code incorrectly uses client.index() with doc and doc_as_upsert fields,
which are only valid for client.update(). To fix this, replace client.index()
with client.update() and pass the document inside the doc field along with
doc_as_upsert: true to enable upsert behavior. Additionally, add a regression
test to verify that updates are correctly applied and not silently ignored.
Issues:
Dependencies
Upstream:
Description
Testing
Check each PR.
Release Plan
master
Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Chores
Tests