Ir al contenido

Arquitectura

Backend

emafhir SDK

Producto consumidor · emaclinic / emalab / etc.

Worker/App code

EmaFhirClient

tenant-aware

FhirClient core

request · auth · URL builder

ProfileResolver

cache 5min · in-flight dedup

injectMeta

idempotente · async

applyAutoTranslate

opt-in · append-only

search builder

validators

RUN · CURP · RFC · DNI

ref · transaction

auth strategies

clientCredentials · bearer

FHIR R4 types

35 resources + ResourceTypeMap

Supabase emashared.countries

Aidbox FHIR

ORGBAC scoped

emafhir/
├── src/
│ ├── index.ts # Public API (5 grupos de exports)
│ ├── core/ # FhirClient genérico (compat pre-Wave 1)
│ ├── ema-client.ts # EmaFhirClient (extends FhirClient)
│ ├── profile-resolver.ts # ProfileResolver (Supabase runtime)
│ ├── meta-injection.ts # injectMeta async idempotente
│ ├── translate.ts # applyAutoTranslate (opt-in $translate)
│ ├── auth/ # clientCredentials, bearerAuth
│ ├── search/ # SearchBuilder fluent
│ ├── validators/ # RUN, CURP, RFC, DNI
│ ├── types/ # FHIR R4 + Tenant + ResourceTypeMap
│ ├── sdc/ # Questionnaire renderer headless
│ ├── react/ # SDC hooks (useSDCForm)
│ └── helpers.ts # ref, transaction
├── docs/
│ ├── decisions.md # F001-F054
│ ├── adr/ # ADRs formales
│ └── CHANGELOG.md
└── tests/
Aidbox FARFhirClient coreapplyAutoTranslateSupabaseProfileResolverinjectMetaEmaFhirClientProducto consumidorAidbox FARFhirClient coreapplyAutoTranslateSupabaseProfileResolverinjectMetaEmaFhirClientProducto consumidoralt[cache hit (< 5 min)][cache miss / expired]alt[options.translate definido]create(resource, { translate? })1prepareForWrite(resource, tenant)2getProfileUrl(tenant.country, resourceType)3canonical URL4SELECT * FROM emashared.countries5rows activos6canonical URL (in-flight dedup)7resource con meta.profile + meta.tag8applyAutoTranslate(resource, fields)9$translate por field10GET ConceptMap/$translate11target codings12resource enriquecido (append-only)13super.create(resource)14POST /Organization/{id}/fhir/{type}15resource creado16resource17resource (con meta + auth + scoping)18
import {
// Factory clients
createClient, // legacy: FhirClient genérico
createEmaClient, // Wave 1+: EmaFhirClient con tenant + Supabase
// Resolver y meta
ProfileResolver,
injectMeta,
applyAutoTranslate,
// Helpers
ref,
transaction,
search,
// Auth
clientCredentials,
bearerAuth,
} from 'emafhir';
import {
validateRun,
validateCurp,
validateRfc,
validateDni,
} from 'emafhir/validators';

supersede

Después · F050-F054

ProfileResolver

runtime · TTL 5min

Supabase emashared.countries

Vault-managed SoT

invalidate manual

+ in-flight dedup

Antes · F044/F045

src/data/countries.ts

mirror hardcoded

CI: test:countries-sync

guard contra drift

Bumpear SDK por

cada cambio en países

AntesDespués
src/data/countries.ts mirror estáticoProfileResolver lee Supabase runtime
Cada cambio de país requería bump de SDKCambio en Vault → SDK lo refleja en ≤ 5 min
Test test:countries-sync guard CITest smoke contra Aidbox edge (T7)
Productos pinneaban versión exactaProductos no requieren cambios al actualizar países
Hardcoded en buildLazy + cache + dedup de promesas concurrentes

createClient() y la FhirClient core siguen exportados y soportados en 0.6.x — no son deprecated. Los productos pre-Wave 1 los usan directamente y no van a romperse al bumpear el SDK.

Cuándo migrar:

  • Recomendado: durante el refactor del producto correspondiente (Wave 3 del Plan Consolidado), porque ahí ya tocás el código que llama a Aidbox.
  • No urgente: si tu producto no necesita meta-inyección automática ni ProfileResolver runtime, podés seguir con createClient() indefinidamente. La API legacy no tiene fecha de remoción.

Cuándo se va a deprecar:

  • En 1.0.0, createClient queda con @deprecated JSDoc.
  • En 2.0.0, se remueve. Esto está fuera del horizonte del Plan Consolidado.