@afyadigital/rx-engine

中文文档
4.9.0发布于 2026/10/20TypeScriptCommonJS近 30 天下载 2406

Afya Digital Prescription Engine

原始使用文档
文档目录8 节
  1. Installation
  2. API
  3. render
  4. unmount
  5. events
  6. commands
  7. trackUserActivity(click: TrackUserActivityEvent) : Trigger …
  8. React dummy example

Afya Digital: Prescription Engine

Library for consuming Afya Digital Prescription Engine - Frontend integration

Previous version status:

VersionStatus
1.xdeprecated
2.xdeprecated
3.xdeprecated

Installation

# npm
npm install @afyadigital/rx-engine --save

# yarn
yarn add @afyadigital/rx-engine

#pnpm
pnpm add @afyadigital/rx-engine

API

render

Renders the RX Engine App, given a configuration object

EngineConfiguration Object

PropertyTypeDefaultDescription
targetstring-Selector of target element to render the app
authObject { token }-Authentication info object
auth.tokenstring-Physician token(*)
initialValueObject { appointment, patient, medications }-Info used on app initialization
initialValue.appointmentObject { id }-Appointment info object
initialValue.appointment.idstring-Appointment id on host application
initialValue.patientObject { id, name, address }-Patient info object (optional)
initialValue.patient.idstring-Patient id on host application
initialValue.patient.namestring-Patient name on host application
initialValue.patient.civilNamestring-Patient civil name on host application
initialValue.patient.addressstring-Patient full address on host application (optional), free text. Derived from serviceAddress when omitted
initialValue.patient.serviceAddressObject { address, number, neighborhood, city, state, zipCode, complement }-Patient structured address (optional)(**)
initialValue.patient.serviceAddress.addressstring-Street name, up to 512 characters
initialValue.patient.serviceAddress.numberstring-Street number, up to 20 characters
initialValue.patient.serviceAddress.neighborhoodstring-Neighborhood, up to 100 characters
initialValue.patient.serviceAddress.citystring-City, up to 64 characters
initialValue.patient.serviceAddress.statestring-State, a valid UF (two letters) — the casing is normalized
initialValue.patient.serviceAddress.zipCodestring-Zip code (CEP), eight digits — the mask is removed automatically
initialValue.patient.serviceAddress.complementstring-Address complement (optional), up to 100 characters
initialValue.patient.phonestring-Patient phone on host application (optional), eleven digits of length
initialValue.patient.emailstring-Patient email on host application (optional)
initialValue.patient.cpfstring-Patient cpf on host application (optional)
initialValue.patient.heightstring-Patient height on host application (optional), in centimeters (cm)
initialValue.patient.weightstring-Patient weight on host application (optional), in kilos (kg)
initialValue.patient.motherNamestring-Patient mother name on host application (optional)
initialValue.patient.birthdatestring-Patient date of birth (optional), ISO 8601 calendar day YYYY-MM-DD (e.g. 1990-05-20)(***)
initialValue.patient.sex'M' | 'F'-Patient biological sex (optional), M for male and F for female(***)
initialValue.medicationsArray of objects [{ type, title, patientInstruction, printType }]-Medication info object
initialValue.medications[<index>].typestring-Medication type (e.g: product, substance or freeText)
initialValue.medications[<index>].idstring-Medication id sent from external partner (optional if type is freeText)
initialValue.medications[<index>].titlestring-Medication title sent from external partner
initialValue.medications[<index>].patientInstructionstring-Medication instructions for patient, sent from external partner
initialValue.medications[<index>].printTypestring-Medication prescription type (e.g: simple, special and antimicrobial) sent from partner
initialValue.medications[<index>].quantitystring-Medication quantity sent from external (optional)partner
initialValue.medications[<index>].unitstring-Medication quantity unit sent from external (optional) partner
initialValue.medications[<index>].subtitlestring-Medication subtitle sent from external partner (required just if type is product)
initialValue.medications[<index>].descriptionstring-Medication description sent from external partner (required just if type is product)
initialValue.medications[<index>].laboratoryNamestring-Medication laboratory sent from external partner(required just if type is product)
initialValue.medications[<index>].categorystring-Medication category sent from external partner (required just if type is product)
initialValue.medications[<index>].maxPricestring-Medication maximun price sent from external partner (required just if type is product)
initialValue.medications[<index>].availablestring-Medication availability sent from partner (required just if type is product)

* Get the physician authentication token through our api

** serviceAddress is required to issue regulated prescriptions (special, antimicrobial and the ones covered by RDC 1.000/2025). Every field but complement is mandatory: an incomplete serviceAddress is ignored with a warning, and the physician has to fill the address in on the engine. When address is not sent, it is built out of serviceAddress.

*** sex and birthdate are not translated by the lib: it only validates them and forwards them as sent. Do not send male/female or a lowercase m/f — an invalid value is ignored with a warning and the physician fills it in on the engine.

Example:

/** Create a configuration to render the Prescription Engine */

// AppEnvOptions = 'production' | 'development'

const appEnv = "development";

const config: EngineConfig = {
  // target element selector. example: <div id="rx-engine"></div>
  target: `#rx-engine`,
  // physician authentication token
  auth: { token: 'jwt-token' },
  initialValue: {
    appointment: {
      id: '123'
    }
    // patient identification and name to create a prescription with
    patient: {
      id: '123',
      name: 'Jhon Doe',
      civilName: 'Jhonnie',
      address: 'Foo Bar',
      serviceAddress: {
        address: 'Praça da Sé',
        number: '100',
        neighborhood: 'Sé',
        city: 'São Paulo',
        state: 'SP',
        zipCode: '01001000',
        complement: 'Apto 42'
      },
      phone: '45999999999',
      email: '[email protected]',
      cpf: '682.733.635-20',
      height: "179",
      weight: "90",
      motherName: 'Jhoana Doe',
      birthdate: '1990-05-20',
      sex: 'F'
    },
    // medications that could be imported from an external partner
    medications: [
      {
        type: 'freeText',
        title: 'Test Med',
        patientInstruction: '1 pill every morning for 10 days';
        printType: 'simple';
      }
    ]
  },
}

/** Render it on your target element */

render(config, env)

Patient Object

The patient sent on initialValue.patient:

type Patient = {
  id: string;
  name: string;
  cpf?: string;
  civilName?: string;
  motherName?: string;
  address?: string;
  serviceAddress?: ServiceAddress;
  email?: string;
  phone?: string;
  weight?: string;
  height?: string;
  /** ISO 8601 calendar day, `YYYY-MM-DD` (e.g. `1990-05-20`) */
  birthdate?: string;
  /** Closed dictionary: `M` for male, `F` for female */
  sex?: 'M' | 'F';
};

unmount

Clean previous mounted app and listeners

unmount();

events

API so you can register to events from prescription app. Make sure to render the app before subscribing to events.

namedescriptionpayload
'app:init'on app initializationnull
'app:revokedToken'when physician token is expired/invalidnull
'prescription:saved'when user saves the prescriptionSavedPrescriptionEventPayload
'prescription:itemAdded'when user adds another item to prescriptionPrescriptionItemEventPayload
'printConfig:saved'when user saves the print configSavedPrintConfigEventPayload
type FreeTextItem = {
  title: string;
  patientInstruction: string;
  quantity: number;
  unit: string;
};

type MedicationItem = FreeTextItem & {
  id: string;
};

type PrescriptionItemEventPayload = {
  type: 'product' | 'substance' | 'freeText';
  origin: 'user' | 'integration';
  data: FreeTextItem | MedicationItem;
};

Example:

import { events } from '@afyadigital/rx-engine'

const doSomething = (prescriptionItem) => { ... }

// register a callback function to an event
events.listen('prescription:itemAdded', doSomething)

// remove an event listener
events.remove('prescription:itemAdded', doSomething)

// remove all listeners
events.cleanup()
type ServiceAddress = {
  address: string;
  number: string;
  neighborhood: string;
  city: string;
  state: string;
  zipCode: string;
  complement?: string;
};

type Patient = {
  name: string;
  externalId: string;
  address?: string;
  serviceAddress?: ServiceAddress;
  phone?: string;
  email?: string;
  cpf?: string;
  height?: string;
  weight?: string;
  motherName?: string;
};

type UserInput = {
  patientInstruction: string;
  quantity?: number;
  unit?: string;
  printType: PrintTypeEnum; // simple | special | antimicrobial
};

type FreeText = {
  type: 'freeText';
  title: string;
} & UserInput;

type Product = {
  type: 'product';
  id: string;
  title: string;
  subtitle: string;
  description: string;
  laboratoryName: string;
  category: string;
  maxPrice: string;
  available: boolean;
} & UserInput;

type Substance = {
  type: 'substance';
  id: string;
  title: string;
} & UserInput;

type PrescriptionItem = FreeText | Product | Substance;

export type Exam = {
  id: string;
  code: string;
  term: string;
};

export type PrescritableExam = {
  quantity: number;
  type: string;
  exam: Exam;
};

export type ExamPage = {
  items: PrescritableExam[];
  clinicalIndication?: string;
};

export type VaccineBase = {
  title: string;
  patientInstruction: string;
  quantity: number;
};

export type VaccineProduct = {
  id: string;
  type: 'product';
} & VaccineBase;

export type VaccineFreeText = {
  type: 'freeText';
} & VaccineBase;

export type Vaccine = VaccineProduct | VaccineFreeText;

export type VaccinePage = {
  items: Vaccine[];
};

export type Lme = {
  patient: {
    fullName: string;
    height: string;
    isCapable: boolean;
    mothersName: string;
    weight: string;
    responsibleName?: string;
    filledBy: {
      responsible:
        | 'patient'
        | 'patientMother'
        | 'responsible'
        | 'physician'
        | 'other';
      name?: string;
      cpf?: string;
    };
    skinColor: 'branca' | 'preta' | 'parda' | 'amarela' | 'indigena';
    ethnicity?: string;
    document: {
      type: 'cpf' | 'cns';
      value: string;
    };
    email: string;
    phone: string;
  };
  org: {
    cnes: string;
    name: string;
  };
  physician: {
    name: string;
    cns: string;
  };
  treatments: LmeTreatment[];
};

export type LmeTreatment = {
  id: string;
  cid10: string;
  diagnostic: string;
  solicitationDate: string;
  anamnese: string;
  exams: {
    id: string;
    term: string;
    code: string;
    type: string;
    quantity: number;
  }[];
  medications: {
    months: string[];
    name: string;
    id: string;
    type: string;
  }[];

  onTreatment: boolean;
  treatmentReport?: string;

  pdfUrl: string; // LME prescription pdf
  examUrl?: string; // prescription pdf for all exams
  protocols?: string[]; // terms prescriptions
  prescriptions?: {
    // LME medications prescriptions
    simple: LmeMedicationPrescription;
    special: LmeMedicationPrescription[];
    antimicrobial: LmeMedicationPrescription[];
  };
};

export type LmeMedicationPrescription = {
  id: string;
  pdfUrl: string;
  prescriptionDate: string;
  quantity: number;
  medications: string[];
};

export type SavedPrescriptionEventPayload = {
  id: string;
  patient: Patient;
  issuedAt?: string;
  items: PrescriptionItem[];
  exams: ExamPage[];
  vaccines: VaccinePage[];
  pdfUrl?: string;
  lme?: Lme;
};

commands

After engine app was initialized (check 'app:init' event above), you can dispatch events on the engine.

addPrescriptionItem(item: PrescriptionItem) : adds item into prescription.

type ItemFreeText = {
  title: string;
  type: 'freeText';
  patientInstruction: string;
  quantity: number;
  unit: string;
};

type ItemMedication = {
  id: string;
  type: 'product' | 'substance';
  patientInstruction: string;
  quantity: number;
  unit: string;
};

export type PrescriptionItem = ItemFreeText | ItemMedication;

Usage example:

import { commands, events } from '@afyadigital/rx-engine';

const onInit = async () => {
  await commands.addPrescriptionItem({
    title: 'Paracetamol',
    type: 'freeText',
    patientInstruction: 'tomar 2x ao dia com intervalo de 4 horas',
    quantity: 2,
    unit: 'comprimidos',
  });
};

events.listen('app:init', onInit);

savePrescriptionItem(item: SaveItemMedication) : Adds item into prescription or save to add in next prescription.

export type SaveItemMedication = {
  id: string;
  type: 'product' | 'substance';
  patientInstruction: string;
  quantity: number;
  highlight: {
    title: string;
    subtitle?: string;
  };
  unit: {
    singular: string;
    plural: string;
  };
  title: string;
  subtitle: string;
  description: string;
  laboratoryName: string;
  category: string;
  maxPrice: string;
  available: string | boolean;
  listType: string;
  prescriptionType: string;
  ean1: string;
};

Usage example:

import { commands, events } from '@afyadigital/rx-engine';

const onInit = async () => {
  commands.savePrescriptionItem({
    id: '11a111bc-de12-461b-b0fe-62e7a8f83cb0',
    highlight: {
      title: '<mark>Neosaldina</mark>',
    },
    unit: {
      singular: 'comprimido',
      plural: 'comprimidos',
    },
    type: 'product',
    title: 'Neosaldina',
    subtitle: 'Comprimido revestido • 60 un',
    description:
      'Dipirona 300 mg + Mucato de Isometepteno 30 mg + Cafeína 30 mg',
    laboratoryName: 'Takeda',
    category: 'Referência',
    maxPrice: '60,03',
    available: true,
    listType: '',
    prescriptionType: '',
    ean1: '7896641810985',
    patientInstruction: '',
    quantity: 0,
  });
};

events.listen('app:init', onInit);

updateToken(token: string) : Updates the physician token

Usage example:

import { commands, events } from '@afyadigital/rx-engine';

events.listen('revokedToken', async () => {
  const token = await getPhysicianToken(); // check physician login below*

  await commands.updateToken(token);
});

*physician login

updateFullScreen(isFullScreen: boolean) : Updates the engine fullscreen state

Usage example:

import { commands } from '@afyadigital/rx-engine';

await commands.updateFullScreen(true);

searchPrescriptionItem(term: string) : Searches for a prescription item by term.

Usage example:

import { commands } from '@afyadigital/rx-engine';

await commands.searchPrescriptionItem('aspirina');

trackUserActivity(click: TrackUserActivityEvent): Trigger event from user source

enum TrackActivityClickEnum {
  MenuPep = 'menuPep',
}

type TrackUserActivityEvent = {
  click: TrackActivityClickEnum;
};

Usage example:

import { commands } from '@afyadigital/rx-engine'

const handleClick = () => {
  commands.trackUserActivity({ click: TrackActivityClickEnum.MenuPep })
}

return (
  <MenuItem>
    <Button onClick={handleClick}>Prescrição</Button>
  </MenuItem>
)

React dummy example

import { useEffect } from 'react'
import { render, unmount } from '@afyadigital/rx-engine'
import type { EngineConfig } from '@afyadigital/rx-engine'

const TARGET_ID = 'rx-engine-container'

function AfyaPrescription() {
  useEffect(() => {
    const config: EngineConfig = {
      target: `#${TARGET_ID}`,
      auth: { token: 'physician-auth-token' },
      initialValue: {
        patient: {
          id: '123',
          name: 'Jhon Doe',
          civilName: 'Jonnie',
          address: 'Foo Bar',
          serviceAddress: {
            address: 'Praça da Sé',
            number: '100',
            neighborhood: 'Sé',
            city: 'São Paulo',
            state: 'SP',
            zipCode: '01001000',
          },
          phone: '45999999999',
          email: '[email protected]',
          cpf: '682.733.635-20',
          height: '179',
          weight: '90',
          motherName: 'Jhoana Doe',
          birthdate: '1990-05-20',
          sex: 'F',
        },
      },
    }

    render(config)

    return () => unmount()
  }, [])

  return <div id={TARGET_ID} />
}

版本与发布记录

@afyadigital/rx-engine 共发布 51 个版本,首次发布于 2021/06/22;过去 12 个月发布了 5 个版本。

版本发布日期距今
4.9.0latest2026/10/2019 天前
4.8.02026/08/182 个月前
4.7.12026/06/274 个月前
4.6.22026/06/274 个月前
4.7.02026/03/127 个月前
4.6.12025/02/051.8 年前

关于 @afyadigital/rx-engine 的常见问题

@afyadigital/rx-engine 是什么?

Afya Digital Prescription Engine

如何安装 @afyadigital/rx-engine?

在项目目录运行 npm install @afyadigital/rx-engine,或使用 pnpm add / yarn add / bun add。

@afyadigital/rx-engine 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@afyadigital/rx-engine 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@afyadigital/rx-engine 可以商用吗?

@afyadigital/rx-engine 使用 未声明 许可。package.json 没有声明许可证。没有许可证的代码默认保留全部权利,商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括,不构成法律意见,请以许可原文为准。

@afyadigital/rx-engine 的下载量有多少?

根据 npm 官方下载统计,@afyadigital/rx-engine 在 2026/10/05 – 2026/11/03 这 30 天内被下载 2,406 次,日均约 80 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@afyadigital/rx-engine 还在维护吗?

最新版本 4.9.0 发布于 2026/10/20(19 天前);至今共发布 51 个版本,其中过去 12 个月发布了 5 个;首次发布于 2021/06/22。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。