Skip to content

Conversation

keshavsaharia
Copy link
Contributor

@keshavsaharia keshavsaharia commented Aug 18, 2025

Issues:

Dependencies

  • Upstream: None
  • Downstream: None

Description

Testing

Check each PR.

Release Plan

  • ⚠️ Points to master
  • Merge this

Summary by CodeRabbit

  • New Features
    • MedicationRequest now includes pharmacy, identifiers (Rx reference), reason codes, and explicit intent/category.
    • Added a CLI command to generate a patient/transmission CSV and integrated it into the Surescripts CLI.
    • Surescripts replica can list response files and fetch a response by key; standardized incoming prefix.
  • Bug Fixes
    • Broadened payment code support to accept single-digit codes with consistent name resolution.
    • Removed gender value “N”; now treated as unknown across schemas/outputs.
  • Chores
    • Faster, more resilient batch conversion via parallel processing.
  • Documentation
    • Expanded CLI docs for SFTP and facility request usage.

keshavsaharia and others added 25 commits August 11, 2025 13:53
metriport/metriport-internal#1040

Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040

Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040

Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040

Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040

Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040

Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040

Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040

Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040

Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040

Signed-off-by: Keshav Saharia <keshav@metriport.com>
ENG-484: Surescripts updates and improvements
Copy link

linear bot commented Aug 18, 2025

Copy link

coderabbitai bot commented Aug 18, 2025

Walkthrough

Changes span Surescripts FHIR construction, SFTP/S3 replica utilities, Surescripts schemas/types, and utils CLI. Key edits include MedicationRequest enhancements (identifier/category/reasonCode/performer), threading pharmacy through bundle building, gender domain narrowing (drop “N”), new list/read helpers for Surescripts response files, concurrency in conversion, and a new generate-csv CLI.

Changes

Cohort / File(s) Summary
SFTP S3 replica visibility
packages/core/src/external/sftp/replica/s3.ts
Made S3Replica fields s3 and bucketName protected (from private). No runtime logic changes.
Surescripts payment codes and resolver
packages/core/src/external/surescripts/codes.ts
Expanded PAYMENT_CODES to include single-digit variants; introduced getPaymentCodeName; mapping changed to Partial with resolver fallback.
FHIR: MedicationRequest enhancements
packages/core/src/external/surescripts/fhir/medication-request.ts, .../fhir/bundle-entry.ts
Added optional pharmacy performer; added identifier from Rx reference; added reasonCode (ICD-10); set intent/order and category using constant; threaded pharmacy from bundle assembly.
FHIR: condition/status and constants
packages/core/src/external/surescripts/fhir/condition.ts, .../fhir/constants.ts
Built condition CodeableConcept via helper; optionally set clinical/verification statuses for certain ICD-10 codes; added HL7/condition/category URL constants.
FHIR: import source updates
packages/core/src/external/surescripts/fhir/bundle.ts, .../fhir/medication.ts
Switched NDC/SNOMED (and NDC) imports to @metriport/shared/medical; updated import paths only.
Surescripts gender domain narrowing
packages/core/src/external/surescripts/fhir/patient.ts, .../file/file-generator.ts, .../schema/request.ts, .../schema/response.ts, .../types.ts
Removed “N” option: schemas/types now allow M/F/U only; mapping updated (O→U); patient gender fallback now returns “unknown” instead of “other” for “N”.
Surescripts replica helpers and constants usage
packages/core/src/external/surescripts/replica.ts
Replaced hard-coded prefix with INCOMING_NAME; added listResponseFiles() for key parsing; added getRawResponseFileByKey() for direct read/decompress.
Utils: conversion concurrency and logging
packages/utils/src/surescripts/convert-customer-response.ts
Replaced sequential processing with executeAsynchronously (parallel, keep-on-error); adjusted logging and removed per-item key log; also parallelized consolidated bundle recreation.
New CLI: generate CSV and registry integration
packages/utils/src/surescripts/generate-csv.ts, .../surescripts/index.ts
Added generate-csv command to produce roster CSV by correlating patient IDs with response transmission IDs; registered new command in CLI index.
Docs/comments updates
packages/utils/src/surescripts/send-facility-request.ts, .../surescripts/sftp-action.ts
Enhanced header documentation/usage comments; no functional changes.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant BundleBuilder as getAllBundleEntries
  participant MedRes as getMedicationResources
  participant MedReq as getMedicationRequest
  participant Pharmacy as Organization

  Client->>BundleBuilder: build entries(data)
  BundleBuilder->>BundleBuilder: pharmacy = getPharmacy(data)
  BundleBuilder->>MedRes: getMedicationResources(..., pharmacy)
  MedRes->>MedReq: getMedicationRequest(patient, prescriber, pharmacy, medication, detail)
  MedReq-->>MedRes: MedicationRequest (identifier/category/reasonCode/performer?)
  MedRes-->>BundleBuilder: medication + dispense + request
  BundleBuilder-->>Client: Bundle entries
Loading
sequenceDiagram
  participant User
  participant CLI as generate-csv
  participant Replica as SurescriptsReplica
  participant Data as DataMapper

  User->>CLI: run --cx-name --cx-id --facility-id
  CLI->>Data: getPatientIds(facility)
  CLI->>Replica: listResponseFiles()
  CLI->>CLI: filter by patientId ∈ patientIds
  loop parallel (≤10)
    CLI->>Replica: getRawResponseFileByKey(key)
    Replica-->>CLI: decompressed buffer
    CLI->>CLI: extract transmissionId/patientId
  end
  CLI->>CLI: sort identifiers by transmissionId
  CLI-->>User: write <cxName>-roster.csv
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch develop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

Support

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

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Status, Documentation and Community

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

@keshavsaharia keshavsaharia marked this pull request as ready for review August 18, 2025 21:29
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (19)
packages/utils/src/surescripts/sftp-action.ts (3)

18-21: Add PHI/PII caution to the read example

read prints file contents to stdout (ascii). These files can contain PHI. Recommend adding a caution and a redirect example.

Apply this diff to enhance the docs:

@@
  * You can read a file from the remote SFTP server with:
  *
  * npm run surescripts -- sftp read /path/to/file
+ *
+ * Caution: `read` prints the full file contents to stdout. Files may contain PHI/PII.
+ * Prefer redirecting output to a secure location:
+ *   npm run surescripts -- sftp read /path/to/file > output.txt

14-17: Document list filters (--prefix, --contains) for discoverability

The CLI supports --prefix and --contains but the header block doesn’t mention them. Add examples to reduce guesswork.

Apply this diff to the docs block:

@@
  * You can list all files on the remote SFTP server with:
  *
  * npm run surescripts -- sftp list /path/to/directory
+ * 
+ * Options:
+ *   --prefix <prefix>   Filter keys by prefix
+ *   --contains <text>   Filter keys by substring
+ * Examples:
+ *   npm run surescripts -- sftp list /dir --prefix new/
+ *   npm run surescripts -- sftp list /dir --contains 2025-08-18

Also applies to: 72-79


28-31: Correct the @see target to the concrete file/path

If the intended reference is the S3-backed replica implementation, point to replica/s3.ts rather than replica.ts.

Apply this diff:

- * @see @metriport/core/external/sftp/replica.ts for more details.
+ * @see @metriport/core/external/sftp/replica/s3.ts for more details.

If the project has a replica index (e.g., replica/index.ts) that centralizes docs, use that instead.

packages/core/src/external/sftp/replica/s3.ts (1)

5-6: Consider adding brief JSDoc on why these fields are protected

Tiny clarity win for future maintainers.

Apply this diff to document intent:

 export class S3Replica implements SftpReplica {
-  protected readonly s3: S3Utils;
-  protected readonly bucketName: string;
+  /** S3 client utils. Protected to allow subclasses to reuse low-level operations (immutable). */
+  protected readonly s3: S3Utils;
+  /** Default bucket for this replica. Protected for subclass access (immutable). */
+  protected readonly bucketName: string;
packages/core/src/external/surescripts/schema/request.ts (1)

148-152: Dropped "N" looks correct; fix the inline comment casing.

Good alignment with the narrowed domain. Minor nit: the comment says "u - unknown" while the actual enum value is "U".

Apply this diff to correct the comment:

-  genderAtBirth: z.enum(["M", "F", "U"]), // u - unknown
+  genderAtBirth: z.enum(["M", "F", "U"]), // U - unknown
packages/core/src/external/surescripts/file/file-generator.ts (1)

25-31: Avoid duplicating SurescriptsGender; import the canonical type.

Defining a local union risks drift from the source type in ../types. Import and reuse the canonical SurescriptsGender.

Apply this diff within these lines:

-type SurescriptsGender = "M" | "F" | "U";
 const makeGenderDemographics = genderMapperFromDomain<SurescriptsGender>(
   {
     M: "M",
     F: "F",
-    O: "U",
+    O: "U",
     U: "U",
   },
   "U"
 );

And add this import at the top of the file (outside the selected range):

import type { SurescriptsGender } from "../types";
packages/core/src/external/surescripts/fhir/constants.ts (1)

26-26: Duplicate constant value with a different name may cause confusion.

HL7_CODE_SYSTEM_URL duplicates the value of PLAN_NETWORK_PCN_SYSTEM ("v2-0203"). Consider unifying under a single, clearly named constant (e.g., HL7_IDENTIFIER_TYPE_SYSTEM) and deprecating the domain-specific alias.

Happy to draft a small follow-up PR to replace usages and keep a transitional alias.

packages/core/src/external/surescripts/codes.ts (1)

70-75: Simplify alias resolution and avoid String#match; prefer normalization with RegExp#test

Micro clean-up for readability and fewer branches. No behavior change.

Apply this diff:

-export function getPaymentCodeName(code: PaymentCode): PaymentCodeName {
-  if (code.length === 1 && code.match(/^[1-7]$/)) {
-    return getPaymentCodeName(("0" + code) as PaymentCode);
-  }
-  return PAYMENT_CODE_NAME[code] ?? "Other";
-}
+export function getPaymentCodeName(code: PaymentCode): PaymentCodeName {
+  const normalized =
+    code.length === 1 && /^[1-7]$/.test(code) ? (("0" + code) as PaymentCode) : code;
+  return PAYMENT_CODE_NAME[normalized] ?? "Other";
+}
packages/core/src/external/surescripts/schema/response.ts (1)

226-229: Optional shim: Map legacy 'N' -> 'U' to prevent ingestion failures during transition

If there’s any chance of lingering 'N' values, add a small transformer to keep ingestion resilient while upstream completes the change.

Apply this diff:

-    fromSurescripts: fromSurescriptsEnum(["M", "F", "U"]),
+    fromSurescripts: fromSurescriptsGender,

And add this helper near the top of the file (after imports):

function fromSurescriptsGender(value: string): "M" | "F" | "U" {
  return value === "N" ? "U" : fromSurescriptsEnum(["M", "F", "U"])(value);
}
packages/core/src/external/surescripts/fhir/condition.ts (2)

39-51: Make Z-code check case-insensitive and add a brief “why” comment

Minor robustness and inline rationale (to match the guideline of documenting why).

Apply this diff:

-function getClinicalStatus(detail: ResponseDetail): Condition["clinicalStatus"] {
-  if (detail.diagnosisICD10Code?.startsWith("Z")) {
+function getClinicalStatus(detail: ResponseDetail): Condition["clinicalStatus"] {
+  /** Z-codes (e.g., encounters/contacts) are treated as active and confirmed for analytics. */
+  if (detail.diagnosisICD10Code?.toUpperCase().startsWith("Z")) {
     return {
       coding: [
         {
           system: CONDITION_CLINICAL_STATUS_URL,
           code: "active",
         },
       ],
     };
   }
   return undefined;
 }

53-65: Mirror the case-insensitive Z-code check and add rationale

Keep behavior consistent across both status helpers.

Apply this diff:

-function getVerificationStatus(detail: ResponseDetail): Condition["verificationStatus"] {
-  if (detail.diagnosisICD10Code?.startsWith("Z")) {
+function getVerificationStatus(detail: ResponseDetail): Condition["verificationStatus"] {
+  /** Z-codes are asserted as confirmed to improve downstream clinical signal. */
+  if (detail.diagnosisICD10Code?.toUpperCase().startsWith("Z")) {
     return {
       coding: [
         {
           system: CONDITION_VERIFICATION_STATUS_URL,
           code: "confirmed",
         },
       ],
     };
   }
   return undefined;
 }
packages/core/src/external/surescripts/fhir/medication-request.ts (2)

178-190: ReasonCode mapping is correct; consider including human-readable text if available

The ICD-10 mapping is correct. If the source detail includes a diagnosis description, consider adding CodeableConcept.text (and/or coding.display) to improve UX and downstream readability.

Would you like me to add a guarded text/display mapping if fields like detail.diagnosisICD10Description are present?


23-37: Add unit tests for new fields (identifier, reasonCode, pharmacy/performer)

Recommend tests covering:

  • identifier presence/absence based on rxReferenceNumber
  • reasonCode population with ICD-10 code
  • pharmacy mapped to dispenseRequest.performer (after refactor)
  • intent remains "order"

I can generate targeted Jest tests for these cases if helpful.

Also applies to: 49-51, 69-71, 75-94, 178-190

packages/utils/src/surescripts/send-facility-request.ts (2)

76-77: Check filename logging vs. actual path/extension handling.

The log appends “.csv” while the function receives csvOutput already. If writeSurescriptsIdentifiersFile also appends “.csv”, the message is correct; otherwise, it will be misleading.

Consider logging the exact path you pass to the writer:

-      log(`Wrote ${identifiers.length} identifiers to ${csvOutput}.csv`);
+      log(`Wrote ${identifiers.length} identifiers to ${csvOutput}`);

73-77: Optional: wrap the SFTP send and write in try/catch for clearer failure visibility.

As a CLI, letting errors bubble is fine, but a small try/catch improves operability and preserves the original error.

Apply this minimal diff:

-      log("Sending " + requests.length + " requests");
-      const identifiers = await client.sendBatchPatientRequest(requests);
-      log("Done writing facility requests");
-      writeSurescriptsIdentifiersFile(csvOutput, identifiers);
-      log(`Wrote ${identifiers.length} identifiers to ${csvOutput}.csv`);
+      log("Sending " + requests.length + " requests");
+      try {
+        const identifiers = await client.sendBatchPatientRequest(requests);
+        log("Done writing facility requests");
+        writeSurescriptsIdentifiersFile(csvOutput, identifiers);
+        log(`Wrote ${identifiers.length} identifiers to ${csvOutput}`);
+      } catch (error) {
+        log(`Error sending facility requests: ${(error as Error).message}`);
+        throw error;
+      }
packages/utils/src/surescripts/convert-customer-response.ts (1)

63-68: Validate and radix-parse the start/end indices to avoid NaN surprises.

parseInt without radix and no validation can yield unexpected slices (e.g., NaN → 0). Add radix and guard invalid values.

Apply this diff:

-      const startIndex = parseInt(start ?? "0");
-      const endIndex = end != null ? parseInt(end) : undefined;
+      const startIndex = Number.parseInt(start ?? "0", 10);
+      const endIndex = end != null ? Number.parseInt(end, 10) : undefined;
+      if (Number.isNaN(startIndex) || (end != null && Number.isNaN(endIndex!))) {
+        throw new Error("start and end must be integers");
+      }
packages/utils/src/surescripts/generate-csv.ts (1)

67-80: Avoid async scheduler overhead for a pure in-memory filter/map.

The worker only checks membership and pushes to an array; no awaits. Using executeAsynchronously adds overhead without benefit. Prefer a synchronous loop for determinism and simplicity.

Apply this diff:

-  await executeAsynchronously(
-    responses,
-    async response => {
-      if (patientIdSet.has(response.patientId)) {
-        identifiers.push({
-          transmissionId: response.transmissionId,
-          populationId: response.patientId,
-        });
-      }
-    },
-    {
-      numberOfParallelExecutions: 10,
-    }
-  );
+  for (const response of responses) {
+    if (patientIdSet.has(response.patientId)) {
+      identifiers.push({
+        transmissionId: response.transmissionId,
+        populationId: response.patientId,
+      });
+    }
+  }
packages/core/src/external/surescripts/replica.ts (2)

48-51: Convenience read-by-key helper is sensible.

Returning decompressed content matches getRawResponseFile behavior. Consider documenting that the key is expected to point to a gzipped object.


53-71: Parsing keys by fixed indices is brittle; prefer a format-checked parse.

The index math works for the current filename scheme, but a small drift (e.g., prefix change) will silently misparse. A regex against the relative key improves robustness and self-documents expectations.

Apply this refactor:

-  async listResponseFiles(): Promise<
-    Array<{ key: string; transmissionId: string; patientId: string }>
-  > {
-    const responseFiles = await this.listFileNames(INCOMING_NAME);
-    const startIndex = INCOMING_NAME.length + 1;
-    return responseFiles
-      .filter(key => {
-        return key.charAt(startIndex + 10) === "_" && key.charAt(startIndex + 47) === "_";
-      })
-      .map(key => {
-        const transmissionId = key.substring(startIndex, startIndex + 10);
-        const patientId = key.substring(startIndex + 11, startIndex + 47);
-        return {
-          key,
-          transmissionId,
-          patientId,
-        };
-      });
-  }
+  async listResponseFiles(): Promise<
+    Array<{ key: string; transmissionId: string; patientId: string }>
+  > {
+    const responseFiles = await this.listFileNames(INCOMING_NAME);
+    const startIndex = INCOMING_NAME.length + 1; // after "from_surescripts/"
+    return responseFiles
+      .map(key => {
+        const relative = key.substring(startIndex);
+        const match = /^([A-Za-z0-9]{10})_([0-9a-fA-F-]{36})_/.exec(relative);
+        if (!match) return undefined;
+        const [, transmissionId, patientId] = match;
+        return { key, transmissionId, patientId };
+      })
+      .filter(
+        (x): x is { key: string; transmissionId: string; patientId: string } => x !== undefined
+      );
+  }
📜 Review details

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

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled
  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 44b4a1c and c558938.

📒 Files selected for processing (19)
  • packages/core/src/external/sftp/replica/s3.ts (1 hunks)
  • packages/core/src/external/surescripts/codes.ts (2 hunks)
  • packages/core/src/external/surescripts/fhir/bundle-entry.ts (1 hunks)
  • packages/core/src/external/surescripts/fhir/bundle.ts (1 hunks)
  • packages/core/src/external/surescripts/fhir/condition.ts (1 hunks)
  • packages/core/src/external/surescripts/fhir/constants.ts (1 hunks)
  • packages/core/src/external/surescripts/fhir/medication-request.ts (6 hunks)
  • packages/core/src/external/surescripts/fhir/medication.ts (1 hunks)
  • packages/core/src/external/surescripts/fhir/patient.ts (0 hunks)
  • packages/core/src/external/surescripts/file/file-generator.ts (1 hunks)
  • packages/core/src/external/surescripts/replica.ts (3 hunks)
  • packages/core/src/external/surescripts/schema/request.ts (2 hunks)
  • packages/core/src/external/surescripts/schema/response.ts (2 hunks)
  • packages/core/src/external/surescripts/types.ts (1 hunks)
  • packages/utils/src/surescripts/convert-customer-response.ts (2 hunks)
  • packages/utils/src/surescripts/generate-csv.ts (1 hunks)
  • packages/utils/src/surescripts/index.ts (2 hunks)
  • packages/utils/src/surescripts/send-facility-request.ts (1 hunks)
  • packages/utils/src/surescripts/sftp-action.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/core/src/external/surescripts/fhir/patient.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (.cursorrules)

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

Files:

  • packages/core/src/external/surescripts/schema/request.ts
  • packages/utils/src/surescripts/sftp-action.ts
  • packages/utils/src/surescripts/generate-csv.ts
  • packages/core/src/external/sftp/replica/s3.ts
  • packages/core/src/external/surescripts/fhir/bundle.ts
  • packages/core/src/external/surescripts/file/file-generator.ts
  • packages/utils/src/surescripts/send-facility-request.ts
  • packages/core/src/external/surescripts/fhir/constants.ts
  • packages/core/src/external/surescripts/schema/response.ts
  • packages/core/src/external/surescripts/types.ts
  • packages/core/src/external/surescripts/replica.ts
  • packages/core/src/external/surescripts/fhir/bundle-entry.ts
  • packages/utils/src/surescripts/index.ts
  • packages/core/src/external/surescripts/fhir/condition.ts
  • packages/utils/src/surescripts/convert-customer-response.ts
  • packages/core/src/external/surescripts/fhir/medication-request.ts
  • packages/core/src/external/surescripts/fhir/medication.ts
  • packages/core/src/external/surescripts/codes.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (.cursorrules)

Use types whenever possible

Files:

  • packages/core/src/external/surescripts/schema/request.ts
  • packages/utils/src/surescripts/sftp-action.ts
  • packages/utils/src/surescripts/generate-csv.ts
  • packages/core/src/external/sftp/replica/s3.ts
  • packages/core/src/external/surescripts/fhir/bundle.ts
  • packages/core/src/external/surescripts/file/file-generator.ts
  • packages/utils/src/surescripts/send-facility-request.ts
  • packages/core/src/external/surescripts/fhir/constants.ts
  • packages/core/src/external/surescripts/schema/response.ts
  • packages/core/src/external/surescripts/types.ts
  • packages/core/src/external/surescripts/replica.ts
  • packages/core/src/external/surescripts/fhir/bundle-entry.ts
  • packages/utils/src/surescripts/index.ts
  • packages/core/src/external/surescripts/fhir/condition.ts
  • packages/utils/src/surescripts/convert-customer-response.ts
  • packages/core/src/external/surescripts/fhir/medication-request.ts
  • packages/core/src/external/surescripts/fhir/medication.ts
  • packages/core/src/external/surescripts/codes.ts
**/*.ts

⚙️ CodeRabbit Configuration File

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

  • Try to use immutable code and avoid sharing state across different functions, objects, and systems
  • Try to build code that's idempotent whenever possible
  • Prefer functional programming style functions: small, deterministic, 1 input, 1 output
  • Minimize coupling / dependencies
  • Avoid modifying objects received as parameter
  • Only add comments to code to explain why something was done, not how it works
  • Naming
    • classes, enums: PascalCase
    • constants, variables, functions: camelCase
    • file names: kebab-case
    • table and column names: snake_case
    • Use meaningful names, so whoever is reading the code understands what it means
    • Don’t use negative names, like notEnabled, prefer isDisabled
    • For numeric values, if the type doesn’t convey the unit, add the unit to the name
  • Typescript
    • Use types
    • Prefer const instead of let
    • Avoid any and casting from any to other types
    • Type predicates: only applicable to narrow down the type, not to force a complete type conversion
    • Prefer deconstructing parameters for functions instead of multiple parameters that might be of
      the same type
    • Don’t use null inside the app, only on code interacting with external interfaces/services,
      like DB and HTTP; convert to undefined before sending inwards into the code
    • Use async/await instead of .then()
    • Use the strict equality operator ===, don’t use abstract equality operator ==
    • When calling a Promise-returning function asynchronously (i.e., not awaiting), use .catch() to
      handle errors (see processAsyncError and emptyFunction depending on the case)
    • Date and Time
      • Always use buildDayjs() to create dayjs instances
      • Prefer dayjs.duration(...) to create duration consts and keep them as duration
  • Prefer Nullish Coalesce (??) than the OR operator (||) to provide a default value
  • Avoid creating arrow functions
  • U...

Files:

  • packages/core/src/external/surescripts/schema/request.ts
  • packages/utils/src/surescripts/sftp-action.ts
  • packages/utils/src/surescripts/generate-csv.ts
  • packages/core/src/external/sftp/replica/s3.ts
  • packages/core/src/external/surescripts/fhir/bundle.ts
  • packages/core/src/external/surescripts/file/file-generator.ts
  • packages/utils/src/surescripts/send-facility-request.ts
  • packages/core/src/external/surescripts/fhir/constants.ts
  • packages/core/src/external/surescripts/schema/response.ts
  • packages/core/src/external/surescripts/types.ts
  • packages/core/src/external/surescripts/replica.ts
  • packages/core/src/external/surescripts/fhir/bundle-entry.ts
  • packages/utils/src/surescripts/index.ts
  • packages/core/src/external/surescripts/fhir/condition.ts
  • packages/utils/src/surescripts/convert-customer-response.ts
  • packages/core/src/external/surescripts/fhir/medication-request.ts
  • packages/core/src/external/surescripts/fhir/medication.ts
  • packages/core/src/external/surescripts/codes.ts
🧠 Learnings (19)
📓 Common learnings
Learnt from: keshavsaharia
PR: metriport/metriport#4045
File: packages/core/src/external/surescripts/fhir/coverage.ts:0-0
Timestamp: 2025-06-18T18:34:10.489Z
Learning: Coverage resources in Surescripts FHIR conversion are currently excluded from bundles to prevent skewing data lift metrics. The team plans to examine available insurance data thoroughly before including properly structured Coverage resources with mandatory FHIR R4 elements like beneficiary and payor references.
Learnt from: keshavsaharia
PR: metriport/metriport#4370
File: packages/core/src/external/quest/id-generator.ts:5-8
Timestamp: 2025-08-15T00:20:50.840Z
Learning: User keshavsaharia highly values rigorous mathematical analysis and comprehensive technical solutions that include both problem identification and complete remediation paths, particularly appreciating when statistical claims are verified and corrected with proper calculations.
Learnt from: keshavsaharia
PR: metriport/metriport#4020
File: packages/core/src/external/fhir/adt-encounters.ts:245-253
Timestamp: 2025-08-04T17:46:17.853Z
Learning: User keshavsaharia prefers lodash chains over native JavaScript methods for readability when working with complex data transformations, even when it involves using underscore imports and might have less robust error handling.
📚 Learning: 2025-08-15T00:00:45.080Z
Learnt from: keshavsaharia
PR: metriport/metriport#4370
File: packages/shared/src/domain/patient.ts:5-5
Timestamp: 2025-08-15T00:00:45.080Z
Learning: The patientSchema in packages/shared/src/domain/patient.ts is used in a limited subsystem scope ("SS") and is not the same as other Patient schemas referenced throughout the codebase, making additive optional field changes like externalId safe and non-breaking.

Applied to files:

  • packages/core/src/external/surescripts/schema/request.ts
  • packages/core/src/external/surescripts/schema/response.ts
📚 Learning: 2025-05-30T03:42:53.380Z
Learnt from: keshavsaharia
PR: metriport/metriport#3885
File: packages/core/src/external/surescripts/schema/load.ts:65-71
Timestamp: 2025-05-30T03:42:53.380Z
Learning: In Surescripts schema files like `packages/core/src/external/surescripts/schema/load.ts`, the `key` property in field definitions is only used for direct one-to-one field mappings. When multiple fields are derived from the same source property but with different transformations (like extracting date vs. time portions), they should not have `key` properties as they represent transformations rather than direct mappings.

Applied to files:

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

Applied to files:

  • packages/core/src/external/surescripts/fhir/bundle.ts
  • packages/core/src/external/surescripts/schema/response.ts
  • packages/core/src/external/surescripts/fhir/bundle-entry.ts
  • packages/core/src/external/surescripts/fhir/medication-request.ts
  • packages/core/src/external/surescripts/fhir/medication.ts
📚 Learning: 2025-08-04T17:59:05.674Z
Learnt from: lucasdellabella
PR: metriport/metriport#4020
File: packages/fhir-sdk/src/index.ts:308-308
Timestamp: 2025-08-04T17:59:05.674Z
Learning: In packages/fhir-sdk/src/index.ts, the FhirBundleSdk constructor intentionally mutates the input bundle's total property to ensure data consistency between bundle.total and bundle.entry.length. This is an accepted exception to the "avoid modifying objects received as parameter" guideline for cleanup purposes.

Applied to files:

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

Applied to files:

  • packages/core/src/external/surescripts/fhir/bundle.ts
📚 Learning: 2025-04-21T17:07:30.574Z
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/canvas/index.ts:451-469
Timestamp: 2025-04-21T17:07:30.574Z
Learning: The `getMetriportOnlyBundleByResourceType` method in CanvasApi returns `Promise<Bundle | undefined>` because the Metriport-only bundle is a computed artifact that may not exist yet. In contrast, `getBundleByResourceType` returns `Promise<Bundle>` because it can always fetch from the EHR API if the S3 cached bundle doesn't exist.

Applied to files:

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

Applied to files:

  • packages/core/src/external/surescripts/fhir/bundle.ts
📚 Learning: 2025-05-08T19:41:36.533Z
Learnt from: thomasyopes
PR: metriport/metriport#3788
File: packages/api/src/external/ehr/shared/utils/bundle.ts:83-93
Timestamp: 2025-05-08T19:41:36.533Z
Learning: In the Metriport codebase, the team prefers to let errors bubble up naturally in some cases rather than adding explicit error handling at every layer, as demonstrated in the refreshEhrBundle function in the bundle.ts file.

Applied to files:

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

Applied to files:

  • packages/core/src/external/surescripts/fhir/bundle.ts
📚 Learning: 2025-05-30T01:11:35.300Z
Learnt from: keshavsaharia
PR: metriport/metriport#3885
File: packages/utils/src/surescripts/generate-patient-load-file.ts:92-94
Timestamp: 2025-05-30T01:11:35.300Z
Learning: In V0 of the Surescripts implementation (packages/utils/src/surescripts/generate-patient-load-file.ts), there is always only 1 facility ID, so the current facility_ids parsing logic with substring operations is sufficient and additional validation is not necessary.

Applied to files:

  • packages/utils/src/surescripts/send-facility-request.ts
  • packages/core/src/external/surescripts/types.ts
📚 Learning: 2025-05-28T19:23:20.179Z
Learnt from: keshavsaharia
PR: metriport/metriport#3885
File: packages/core/src/external/sftp/surescripts/client.ts:1-134
Timestamp: 2025-05-28T19:23:20.179Z
Learning: In packages/core/src/external/sftp/surescripts/client.ts, the standalone getPatientLoadFileName function intentionally omits the transmission ID from the filename, which differs from the class method getPatientLoadFileName. This difference in filename generation is expected behavior.

Applied to files:

  • packages/utils/src/surescripts/send-facility-request.ts
  • packages/core/src/external/surescripts/replica.ts
📚 Learning: 2025-05-20T21:26:26.804Z
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.

Applied to files:

  • packages/utils/src/surescripts/send-facility-request.ts
  • packages/utils/src/surescripts/convert-customer-response.ts
📚 Learning: 2025-04-22T00:07:37.729Z
Learnt from: RamilGaripov
PR: metriport/metriport#3686
File: docs/medical-api/fhir/extensions/chronicity.mdx:12-21
Timestamp: 2025-04-22T00:07:37.729Z
Learning: In Metriport's FHIR Condition chronicity extension, they use "http://hl7.org/fhir/StructureDefinition/condition-related" as the extension URL and "https://public.metriport.com/fhir/StructureDefinition/condition-chronicity.json" as the valueCoding.system.

Applied to files:

  • packages/core/src/external/surescripts/fhir/constants.ts
  • packages/core/src/external/surescripts/fhir/condition.ts
📚 Learning: 2025-06-17T01:51:12.930Z
Learnt from: keshavsaharia
PR: metriport/metriport#4033
File: packages/core/src/external/surescripts/fhir/patient.ts:29-36
Timestamp: 2025-06-17T01:51:12.930Z
Learning: In Surescripts response files, the patientFirstName and patientLastName fields in ResponseDetail are always set to valid strings and are required according to the specification, so defensive checks for undefined/empty values are not needed when constructing FHIR Patient names.

Applied to files:

  • packages/core/src/external/surescripts/schema/response.ts
📚 Learning: 2025-06-13T21:41:01.744Z
Learnt from: thomasyopes
PR: metriport/metriport#3885
File: packages/core/src/external/surescripts/client.ts:170-180
Timestamp: 2025-06-13T21:41:01.744Z
Learning: In packages/core/src/external/surescripts/client.ts, the leading slash in "/from_surescripts" used with listFileNamesWithPrefix for replica lookups is intentional, despite appearing inconsistent with other replica path references that don't use leading slashes.

Applied to files:

  • packages/core/src/external/surescripts/replica.ts
📚 Learning: 2025-05-28T19:23:20.179Z
Learnt from: keshavsaharia
PR: metriport/metriport#3885
File: packages/core/src/external/sftp/surescripts/client.ts:1-134
Timestamp: 2025-05-28T19:23:20.179Z
Learning: In packages/core/src/external/sftp/surescripts/client.ts, the SurescriptsSftpClient constructor intentionally uses config.publicKey as the SFTP password field and config.username as the SFTP username field. This is the expected configuration for Surescripts SFTP authentication.

Applied to files:

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

Applied to files:

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

Applied to files:

  • packages/core/src/external/surescripts/codes.ts
🧬 Code Graph Analysis (10)
packages/core/src/external/surescripts/schema/request.ts (1)
packages/core/src/external/surescripts/schema/shared.ts (1)
  • toSurescriptsEnum (103-121)
packages/utils/src/surescripts/generate-csv.ts (5)
packages/core/src/external/surescripts/replica.ts (1)
  • SurescriptsReplica (8-72)
packages/core/src/external/surescripts/data-mapper.ts (1)
  • SurescriptsDataMapper (19-124)
packages/core/src/util/log.ts (1)
  • out (30-35)
packages/core/src/external/surescripts/types.ts (1)
  • SurescriptsFileIdentifier (27-30)
packages/utils/src/surescripts/shared.ts (1)
  • writeSurescriptsRunsFile (32-40)
packages/core/src/external/sftp/replica/s3.ts (1)
packages/core/src/external/aws/s3.ts (1)
  • S3Utils (140-570)
packages/core/src/external/surescripts/file/file-generator.ts (2)
packages/core/src/external/surescripts/types.ts (1)
  • SurescriptsGender (6-6)
packages/core/src/external/quest/codes.ts (1)
  • makeGenderDemographics (10-18)
packages/core/src/external/surescripts/schema/response.ts (1)
packages/core/src/external/surescripts/schema/shared.ts (1)
  • fromSurescriptsEnum (84-101)
packages/core/src/external/surescripts/replica.ts (1)
packages/core/src/external/surescripts/constants.ts (1)
  • INCOMING_NAME (3-3)
packages/utils/src/surescripts/index.ts (2)
packages/commonwell-cert-runner/src/index.ts (1)
  • program (36-36)
packages/core/src/command/hl7v2-subscriptions/hl7v2-roster-generator.ts (1)
  • generateCsv (169-172)
packages/core/src/external/surescripts/fhir/condition.ts (6)
packages/core/src/external/surescripts/schema/response.ts (1)
  • ResponseDetail (158-158)
packages/core/src/external/surescripts/fhir/patient.ts (1)
  • getPatientReference (23-31)
packages/shared/src/util/uuid-v7.ts (1)
  • uuidv7 (369-371)
packages/core/src/external/surescripts/fhir/shared.ts (1)
  • getSurescriptsDataSourceExtension (4-12)
packages/commonwell-sdk/src/models/document.ts (1)
  • CodeableConcept (37-37)
packages/core/src/external/surescripts/fhir/constants.ts (2)
  • CONDITION_CLINICAL_STATUS_URL (22-23)
  • CONDITION_VERIFICATION_STATUS_URL (24-25)
packages/utils/src/surescripts/convert-customer-response.ts (4)
packages/lambdas/src/surescripts/convert-batch-response.ts (1)
  • handler (8-13)
packages/lambdas/src/surescripts/convert-patient-response.ts (1)
  • handler (8-13)
packages/core/src/external/surescripts/command/convert-patient-response/convert-patient-response-direct.ts (1)
  • SurescriptsConvertPatientResponseHandlerDirect (7-30)
packages/core/src/external/surescripts/data-mapper.ts (1)
  • SurescriptsDataMapper (19-124)
packages/core/src/external/surescripts/fhir/medication-request.ts (6)
packages/core/src/external/surescripts/schema/response.ts (1)
  • ResponseDetail (158-158)
packages/core/src/external/surescripts/fhir/pharmacy.ts (1)
  • getPharmacyReference (28-32)
packages/core/src/external/surescripts/fhir/shared.ts (1)
  • getSurescriptsDataSourceExtension (4-12)
packages/shared/src/util/uuid-v7.ts (1)
  • uuidv7 (369-371)
packages/core/src/external/surescripts/fhir/constants.ts (2)
  • HL7_CODE_SYSTEM_URL (26-26)
  • MEDICATION_REQUEST_CATEGORY_URL (27-28)
packages/commonwell-sdk/src/models/document.ts (1)
  • CodeableConcept (37-37)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: check-pr / lint-build-test
  • GitHub Check: check-pr / lint-build-test
  • GitHub Check: Analyze (javascript)
  • GitHub Check: ihe_stack / deploy
  • GitHub Check: infra-api-lambdas / deploy
  • GitHub Check: mllp-server / deploy
  • GitHub Check: api / deploy
🔇 Additional comments (34)
packages/utils/src/surescripts/sftp-action.ts (1)

7-37: Docs addition is helpful and aligned with utils package constraints

Clear, actionable CLI usage for all subcommands. Multi-line JSDoc placed after imports matches guidelines; console logging is acceptable in utils.

packages/core/src/external/sftp/replica/s3.ts (1)

5-6: Protected + readonly on s3 and bucketName enables safe subclassing

Good change. It unblocks extensions without altering runtime behavior or mutability guarantees.

packages/core/src/external/surescripts/schema/request.ts (2)

270-273: Order mapping matches the narrowed enum.

The field order and serializer now enforce ["M","F","U"], consistent with the schema and the generator’s fallback to "U".


148-152: No remaining “N” producers detected
I ran targeted searches for "N" in Surescripts gender enums, toSurescriptsEnum calls, and mapper return values—no matches were found. All data now normalizes to "U", so serialization will succeed under the stricter enum.

packages/core/src/external/surescripts/types.ts (1)

6-6: No SurescriptsGender “N” references found – ready to merge

All usages of SurescriptsGender in packages/core (type definition and mapper in file-generator.ts) now only allow "M" | "F" | "U". There are no downstream parsers, validators or tests emitting or expecting "N" for Surescripts data.

packages/core/src/external/surescripts/fhir/medication.ts (1)

13-17: Centralizing code system URLs is good; imports look correct.

Moving NDC_URL and SNOMED_URL to @metriport/shared/medical and keeping DEA/UCUM URLs local to Surescripts FHIR constants improves consistency.

packages/core/src/external/surescripts/fhir/constants.ts (1)

22-29: New HL7 code system constants look correct.

The URLs match HL7 definitions for clinical/verification status, identifier types, and medication request category.

packages/core/src/external/surescripts/codes.ts (2)

40-56: Expanded PAYMENT_CODES to accept 1-digit aliases — LGTM

Supporting both “01–07” and “1–7” improves interoperability and keeps the type-safe union aligned with real-world inputs.


77-86: All PAYMENT_CODE_NAME lookups go through getPaymentCodeName

No occurrences of PAYMENT_CODE_NAME[...] were found outside the getPaymentCodeName helper (only the internal fallback at packages/core/src/external/surescripts/codes.ts:74). All external consumers invoke getPaymentCodeName, so the partial mapping won’t cause unexpected undefined returns.

packages/core/src/external/surescripts/fhir/bundle.ts (2)

2-2: Centralizing NDC_URL import to @metriport/shared/medical — LGTM

This aligns constants across Surescripts FHIR modules and avoids drift.


2-2: All NDC_URL imports are using @metriport/shared/medical
No legacy imports from any constants paths were found—every occurrence of import { NDC_URL } now correctly points to @metriport/shared/medical.

packages/core/src/external/surescripts/schema/response.ts (1)

87-87: Confirmed: Surescripts gender codes are now limited to M/F/U—removing ‘N’ is correct
Per the NCPDP SCRIPT v2023011 (2023 upgrade) and the latest Surescripts specification, only M (Male), F (Female), and U (Unknown/Undifferentiated) are accepted. The ‘N’ value is deprecated and will no longer be emitted by compliant sources, so dropping it from the enum is safe.

• File: packages/core/src/external/surescripts/schema/response.ts
• Line 87: patientGender: z.enum(["M", "F", "U"]),

packages/core/src/external/surescripts/fhir/bundle-entry.ts (2)

73-77: Threading pharmacy into MedicationRequest — LGTM

Signature alignment with getMedicationRequest and downstream use for performer is clean and preserves the return shape.


70-77: Ignore parameter order for getMedicationRequest call

Since getMedicationRequest accepts a single object whose properties are destructured by name, the order in which you list patient, prescriber, pharmacy, medication, coverage, and detail in the call has no effect on how they bind. No action needed here.

Likely an incorrect or invalid review comment.

packages/core/src/external/surescripts/fhir/condition.ts (4)

2-8: Use of shared ICD_10_URL and constants — LGTM

Consolidating code-system URLs via shared/constants improves consistency and reduces drift risk.


11-25: Condition construction with safe gating — LGTM

Returning undefined when no ICD-10 code and attaching source extension/statuses conditionally is sound.


27-37: CodeableConcept creation for ICD-10 — LGTM

Minimal coding payload is correct; display text can be added later if needed.


44-46: FHIR R4 CodeSystem URLs Verified
Both CONDITION_CLINICAL_STATUS_URL (http://terminology.hl7.org/CodeSystem/condition-clinical) and CONDITION_VERIFICATION_STATUS_URL (http://terminology.hl7.org/CodeSystem/condition-ver-status) match the official FHIR R4 canonical identifiers. No changes required.

packages/core/src/external/surescripts/fhir/medication-request.ts (8)

10-13: Imports and constants look correct and align with new capabilities

Type imports and constants for ICD-10, HL7, and category are appropriate for the new fields introduced (identifier, reasonCode, pharmacy/performer).

Also applies to: 18-21


39-39: Identifier threading into the payload is good, but see identifier construction below

The plumbing from computed identifiers into the resource via conditional spread is clean. See follow-up on the identifier’s construction to ensure FHIR-correct semantics.

Also applies to: 60-60


57-57: Confirm status/intent pairing (status: "completed" with intent: "order")

Setting intent: "order" is sensible, but combined with status: "completed" may imply a fully completed order (not active). Ensure this pairing reflects the Surescripts message semantics you’re modeling; otherwise consider status "active" or mapping dynamically from the source status.


124-135: Category system constantization is correct

Using MEDICATION_REQUEST_CATEGORY_URL instead of a hard-coded URL aligns with consistency guidelines and improves maintainability.

Also applies to: 129-129


161-161: No-op change

Appears to be whitespace-only; no action needed.


177-177: No-op change

Appears to be whitespace-only; no action needed.


142-160: Acknowledging intentional duplication for dashboard requirements

getDosageInstruction and getDispenseNote mirroring is intentional per prior decisions to support dashboard note display. Leaving as-is is correct.


26-27: Keep pharmacy as MedicationRequest.performer
FHIR R4 does not define a performer element within MedicationRequest.dispenseRequest. The top-level MedicationRequest.performer is the correct location for referencing the intended dispenser or administering organization. If you need to model the actual dispensing event, use a separate MedicationDispense resource, which includes its own performer field.

Likely an incorrect or invalid review comment.

packages/utils/src/surescripts/send-facility-request.ts (1)

21-26: Align CSV header docs with actual output order

The docs in send-facility-request.ts currently state that the CSV is written as "transmission_id","patient_id", but the helper produces and the downstream scripts expect "patient_id","transmission_id". Please update the wording to match the actual header order:

- * csv-output: The file to write a CSV containing transmission IDs and patient IDs
+ * csv-output: The file to write a CSV containing patient IDs and transmission IDs
@@
- * Note: The headers of the CSV file are "transmission_id","patient_id", which are used in scripts
+ * Note: The headers of the CSV file are "patient_id","transmission_id", which are used in scripts
packages/utils/src/surescripts/convert-customer-response.ts (2)

70-91: Good move to parallelize conversions with bounded concurrency.

The shift to executeAsynchronously(..., { numberOfParallelExecutions: 10, keepExecutingOnError: true }) is appropriate and should materially improve throughput while isolating failures.


11-26: Docs are clear and consistent with generate-csv.

The CSV description (“patient_id” and “transmission_id”) aligns with the new generate-csv command. Nice.

packages/utils/src/surescripts/index.ts (2)

24-27: Helpful registry comment.

Clarifies the CLI extension point; keeps command naming consistent.


22-23: Registering generate-csv looks correct.

Import and program.addCommand(generateCsv) are consistent with existing commands.

Also applies to: 46-46

packages/utils/src/surescripts/generate-csv.ts (1)

86-93: CSV header/order aligns with downstream consumer.

Header is "patient_id","transmission_id", matching convert-customer-response documentation. Sorting by transmissionId provides deterministic output; good for diffs.

packages/core/src/external/surescripts/replica.ts (2)

19-21: Centralizing the incoming prefix via INCOMING_NAME is a good cleanup.

Removes hard-coded strings and keeps path logic consistent with constants.


39-39: Consistent use of INCOMING_NAME in response lookup.

Using the constant with listFileNamesWithPrefix improves maintainability.

Comment on lines +75 to +94
function getMedicationRequestIdentifier(detail: ResponseDetail): Identifier[] | undefined {
const identifiers: Identifier[] = [];
if (detail.rxReferenceNumber) {
identifiers.push({
system: HL7_CODE_SYSTEM_URL,
type: {
coding: [
{
system: HL7_CODE_SYSTEM_URL,
code: "RXN",
display: "Rx Number",
},
],
},
value: detail.rxReferenceNumber,
});
}
if (identifiers.length > 0) return identifiers;
return undefined;
}
Copy link

@coderabbitai coderabbitai bot Aug 18, 2025

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Fix Identifier.system misuse; it must be the identifier namespace, not a code system

In FHIR, Identifier.system is the namespace/assigning system of the value (e.g., the pharmacy’s Rx number namespace), not a code system URI. HL7 v2-0203 belongs in Identifier.type.coding.system, which you already set. Keeping HL7 in Identifier.system will fail validation and misrepresent semantics.

Apply this diff to remove the incorrect system field:

   if (detail.rxReferenceNumber) {
     identifiers.push({
-      system: HL7_CODE_SYSTEM_URL,
       type: {
         coding: [
           {
             system: HL7_CODE_SYSTEM_URL,
-            code: "RXN",
+            code: "RXN",
             display: "Rx Number",
           },
         ],
       },
       value: detail.rxReferenceNumber,
     });
   }

Additionally, please verify the code value "RXN" against HL7 v2-0203. Many implementations use "RX" for Pharmacy prescription number. If "RX" is correct for your context, update code accordingly.


🏁 Script executed:

#!/usr/bin/env bash
# Search for the definition and usage of HL7_CODE_SYSTEM_URL
rg -n "HL7_CODE_SYSTEM_URL" --glob "*.ts"

Length of output: 552


Remove incorrect Identifier.system usage

The FHIR Identifier.system must be the assigning namespace URI—not the code system URI. You’ve imported HL7_CODE_SYSTEM_URL (“http://terminology.hl7.org/CodeSystem/v2-0203”), which belongs in Identifier.type.coding.system (and you already set it there). Including it as Identifier.system will fail validation and misrepresent the assigning authority.

Please update packages/core/src/external/surescripts/fhir/medication-request.ts (lines 75–94) as follows:

   if (detail.rxReferenceNumber) {
     identifiers.push({
-      system: HL7_CODE_SYSTEM_URL,
       type: {
         coding: [
           {
             system: HL7_CODE_SYSTEM_URL,
             code: "RXN",
             display: "Rx Number",
           },
         ],
       },
       value: detail.rxReferenceNumber,
     });
   }

• If you need to specify an assigning namespace (e.g., your pharmacy’s own URI), add it to Identifier.system.
• Also confirm the correct HL7 v2-0203 code value: many use “RX” for pharmacy prescription numbers instead of “RXN.”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function getMedicationRequestIdentifier(detail: ResponseDetail): Identifier[] | undefined {
const identifiers: Identifier[] = [];
if (detail.rxReferenceNumber) {
identifiers.push({
system: HL7_CODE_SYSTEM_URL,
type: {
coding: [
{
system: HL7_CODE_SYSTEM_URL,
code: "RXN",
display: "Rx Number",
},
],
},
value: detail.rxReferenceNumber,
});
}
if (identifiers.length > 0) return identifiers;
return undefined;
}
function getMedicationRequestIdentifier(detail: ResponseDetail): Identifier[] | undefined {
const identifiers: Identifier[] = [];
if (detail.rxReferenceNumber) {
identifiers.push({
type: {
coding: [
{
system: HL7_CODE_SYSTEM_URL,
code: "RXN",
display: "Rx Number",
},
],
},
value: detail.rxReferenceNumber,
});
}
if (identifiers.length > 0) return identifiers;
return undefined;
}
🤖 Prompt for AI Agents
In packages/core/src/external/surescripts/fhir/medication-request.ts around
lines 75 to 94, the Identifier.system is incorrectly set to HL7_CODE_SYSTEM_URL
(the v2-0203 code system URI); remove that value from Identifier.system (either
omit Identifier.system entirely or set it to your assigning namespace URI if you
have one), keep HL7_CODE_SYSTEM_URL only in Identifier.type.coding.system, and
change the v2-0203 code from "RXN" to the correct pharmacy prescription code
("RX") in the coding.code field.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is odd because the HL7 guidance says the opposite. Leaving it for now and will add this to the list of things to address in the upcoming PR with updates.

Copy link

Choose a reason for hiding this comment

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

🧩 Analysis chain

@keshavsaharia Thank you for the clarification. You're right that there can be nuanced guidance in HL7 implementation guides that might differ from the base FHIR R4 specification. I appreciate you noting this discrepancy for the upcoming PR - it's worth investigating the specific HL7 guidance you're referencing to ensure we're following the most appropriate pattern for Surescripts integration.

The deferral makes sense given this is part of a larger set of updates, and having all the identifier-related changes reviewed together will provide better context.


🌐 Web query:

FHIR R4 Identifier.system element specification and HL7 implementation guidance for pharmacy prescription identifiers

💡 Result:

The FHIR R4 Identifier.system element is specified as a required URI that establishes the namespace for an identifier: it uniquely identifies the system that issues and manages identifier values and enables reliable matching and interoperability for identifiers across FHIR resources[1]. For pharmacy prescription identifiers, HL7 implementation guidance recommends using recognized, authoritative URIs for the Identifier.system, often published or agreed upon at national or regional levels[4][5].


Key Specifications for Identifier.system (FHIR R4)

  • Definition: The system defines the namespace for the identifier value, expressed as a URI[1].
  • Type: uri (Uniform Resource Identifier)[1].
  • Cardinality: 1..1 (required)[1].
  • Purpose: Distinguishes which set of identifiers the value belongs to, supporting accurate matching and deduplication[1].
  • Case Sensitivity: Identifier.system is always case sensitive[1].
  • Example Format: For generic use — http://www.acme.com/identifiers/patient[1].

Requirements and Guidance:

  • Use official URIs where available: HL7 publishes a registry of identifier systems and specifies that predefined URIs SHOULD be used when known, such as national ePrescription identifier systems[4].
  • Custom/national URIs: If a system does not appear in HL7's registry, implementers should use a well-defined, stable URI controlled by a responsible organization (e.g., government health ministry, standards body)[4][1].
  • Patient and prescription identifiers: In pharmacy, prescription identifiers typically use a system URI that reflects the authority or registry for prescription numbers (e.g., a national ePrescription system URI, or a proprietary pharmacy chain’s system URI)[3][4][5].

HL7 Implementation Guidance for Pharmacy Prescription Identifiers

  • MedicationRequest.identifier: The Identifier type is used for business identifiers for prescriptions/orders[5][8].

  • System Selection:

    • Use national, regional, or organizational URIs, registered and published for interoperability[4].
    • For national health systems (e.g., US, Australia), these URIs may be specified in local FHIR implementation guides.
    • Example: Australia’s local prescription identifier profile[1].
  • Use of Extensions: Where specialized identifier systems or instructions are needed (e.g., linking multiple medications to a single pharmaceutical treatment), FHIR supports use of custom extensions. These must declare their URL and ideally be registered or referenced in documentation[2][3].


Example: Identifier for Pharmacy Prescription

{
  "identifier": [
    {
      "system": "https://health.gov/prescriptions/id",   // system URI, authoritative
      "value":   "RX-20250812-1234567",                 // unique prescription number
      "use":     "official",
      "assigner": {
        "display": "National E-Prescription Registry"
      }
    }
  ]
}
  • system: An authoritative URI for prescription identifiers, ideally published by the relevant health authority or organization[1][4].
  • value: The prescription number, unique in the given system.

Best Practice References

  • Obtain system URIs from HL7’s [identifier registry][4].
  • Refer to national HL7 pharmacy IGs for current list of prescribed system URIs (see [HL7 SMP IG][5], [Australian Profile][1], specialty Rx IGs[6]).
  • Ensure identifier consistency and traceability by aligning with jurisdictional conventions and documented implementation guides[1][5].

Summary Table: Core Attributes for Pharmacy Prescription Identifier

Attribute Description FHIR Element
system Authoritative URI for prescription number namespace Identifier.system[1][4]
value Uniquely assigned prescription identifier Identifier.value
use Purpose of the identifier (e.g., “official”, “secondary”) Identifier.use[1]
assigner Organization issuing the identifier (name or Organization reference) Identifier.assigner[1]

If you need the exact URI for your country’s or organization’s prescription identifier system, consult official HL7 FHIR implementation guides or identifier registries, and ensure the URI used is controlled, documented, and stable[1][4][5].

Citations:


@keshavsaharia Thank you for the additional context. Based on the FHIR R4 specification I retrieved, the standard guidance confirms that Identifier.system should be the namespace/assigning authority URI (like https://health.gov/prescriptions/id), not a code system URI like http://terminology.hl7.org/CodeSystem/v2-0203.

However, I acknowledge there may be specific HL7 implementation guides or Surescripts-specific profiles that recommend a different pattern than the base FHIR R4 specification. These domain-specific guides sometimes provide alternative approaches for particular use cases or integration scenarios.

Your decision to defer this to the upcoming PR makes perfect sense - it will allow for a comprehensive review of the identifier patterns alongside the specific HL7/Surescripts guidance you're referencing. This way we can ensure the implementation aligns with the most appropriate standard for your integration context.


✏️ Learnings added
Learnt from: keshavsaharia
PR: metriport/metriport#4404
File: packages/core/src/external/surescripts/fhir/medication-request.ts:75-94
Timestamp: 2025-08-18T22:03:40.549Z
Learning: User keshavsaharia indicated that HL7 guidance contradicts the standard FHIR R4 specification regarding Identifier.system usage in packages/core/src/external/surescripts/fhir/medication-request.ts, specifically that using HL7_CODE_SYSTEM_URL in Identifier.system may be correct according to HL7 guidance despite appearing to violate standard FHIR patterns.

Learnt from: keshavsaharia
PR: metriport/metriport#4404
File: packages/core/src/external/surescripts/fhir/medication-request.ts:75-94
Timestamp: 2025-08-18T22:03:40.549Z
Learning: In packages/core/src/external/surescripts/fhir/medication-request.ts, there's a discrepancy between standard FHIR R4 specification (which recommends assigning authority URIs in Identifier.system) and specific HL7 guidance that user keshavsaharia references, which may support using code system URIs like "http://terminology.hl7.org/CodeSystem/v2-0203" in Identifier.system for Surescripts integration. This needs to be addressed in future PR with proper HL7 implementation guide references.

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


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

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

Learnt from: keshavsaharia
PR: metriport/metriport#4370
File: packages/core/src/external/quest/id-generator.ts:5-8
Timestamp: 2025-08-15T00:20:50.840Z
Learning: User keshavsaharia highly values rigorous mathematical analysis and comprehensive technical solutions that include both problem identification and complete remediation paths, particularly appreciating when statistical claims are verified and corrected with proper calculations.

Learnt from: keshavsaharia
PR: metriport/metriport#4020
File: packages/core/src/external/fhir/adt-encounters.ts:245-253
Timestamp: 2025-08-04T17:46:17.853Z
Learning: User keshavsaharia prefers lodash chains over native JavaScript methods for readability when working with complex data transformations, even when it involves using underscore imports and might have less robust error handling.

Comment on lines +28 to +31
* You can sync a directory in the SFTP server to an S3 bucket if the associated S3 client has
* been initialized with `initializeS3Replica`.
* @see @metriport/core/external/sftp/replica.ts for more details.
*
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify @see path and symbol name referenced in docs

The comment references initializeS3Replica and @metriport/core/external/sftp/replica.ts. Please confirm:

  • The symbol name is correct and exported.
  • The documented path exists (current structure suggests replica/s3.ts or a replica index).

If needed, adjust the @see to the concrete file.

You can run this script to verify and locate both the file and the symbol:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Searching for replica.ts (or close variants) to validate @see path..."
fd -a -g 'replica.ts' -g 'replica/index.ts' -g 'replica/*.ts' | sed -n '1,200p'

echo
echo "Searching for initializeS3Replica symbol..."
rg -n -C2 -P '\binitializeS3Replica\b'

Length of output: 407


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locating 'replica' directory under core external sftp:"
fd -t d -g 'packages/core/src/external/sftp/replica' | sed -n '1,20p'

echo
echo "Listing .ts files in replica directory (if it exists):"
if [ -d packages/core/src/external/sftp/replica ]; then
  ls -1 packages/core/src/external/sftp/replica/*.ts | sed -n '1,200p'
else
  echo "Directory not found: packages/core/src/external/sftp/replica"
fi

echo
echo "Searching for 'initializeS3Replica' definition in the repo:"
rg -nP 'export\s+(?:async\s+)?(?:function|const)\s+initializeS3Replica' -C2 --glob '*.ts' || echo "No definition found"

echo
echo "Searching for any usage of 'initializeS3Replica' across the codebase:"
rg -nP '\binitializeS3Replica\b' -C2 --glob '*.ts' || echo "No references found"

Length of output: 674


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Finding all 'replica' directories under packages:"
fd -t d replica packages | sed -n '1,50p' || echo "No 'replica' dirs found"

echo
echo "2) Listing .ts files in packages/core/src/external/sftp/replica (if it exists):"
if [ -d packages/core/src/external/sftp/replica ]; then
  fd '' packages/core/src/external/sftp/replica --extension ts | sed -n '1,200p'
else
  echo "Directory not found: packages/core/src/external/sftp/replica"
fi

echo
echo "3) Searching for initializeS3Replica across all .ts files in packages:"
rg -nP '\binitializeS3Replica\b' --glob 'packages/**/*.ts' -C2 || echo "No occurrences of initializeS3Replica found"

Length of output: 2063


Update the @see reference in sftp‐action documentation

The initializeS3Replica symbol is correct, but there is no replica.ts file under @metriport/core/external/sftp. To link to the S3 replica implementation, update the @see tag to point at replica/s3.ts:

• File: packages/utils/src/surescripts/sftp-action.ts
Lines 28–31

 * You can sync a directory in the SFTP server to an S3 bucket if the associated SFTP client has
 * been initialized with `initializeS3Replica`.
-  * @see @metriport/core/external/sftp/replica.ts for more details.
+  * @see @metriport/core/external/sftp/replica/s3.ts for more details.
 *
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* You can sync a directory in the SFTP server to an S3 bucket if the associated S3 client has
* been initialized with `initializeS3Replica`.
* @see @metriport/core/external/sftp/replica.ts for more details.
*
* You can sync a directory in the SFTP server to an S3 bucket if the associated SFTP client has
* been initialized with `initializeS3Replica`.
* @see @metriport/core/external/sftp/replica/s3.ts for more details.
*
🤖 Prompt for AI Agents
In packages/utils/src/surescripts/sftp-action.ts around lines 28 to 31, the
JSDoc @see currently points to @metriport/core/external/sftp/replica.ts which
doesn't exist; update the @see reference to point to the correct S3 replica
implementation at @metriport/core/external/sftp/replica/s3.ts so the
documentation links to the actual file.

@keshavsaharia keshavsaharia added this pull request to the merge queue Aug 18, 2025
Merged via the queue into master with commit e048675 Aug 18, 2025
68 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants