@opencharts/sme
v0.0.1
Published
Subject Matter Expert (SME) utilities for OpenCharts
Readme
@opencharts/sme
Source mapping engine: apply declarative source mappings with resolution planning.
Overview
@opencharts/sme (Source Mapping Engine) applies a declarative SourceMappingDefinition to a source record, producing:
- Shared resolution inputs (identity parameters per resolvable resource)
- Canonical case resources (with parameters resolved from the record)
- Business key components
- Demand and workflow references
- Source record provenance
No arbitrary JavaScript is executed at mapping time — all transforms are referenced by { name, version } from the normalizer registry.
Tip: For new integrations, prefer
@opencharts/mapper(the pure mapper) +@opencharts/case(the assembler). The SME is best suited for mappings that need an explicitshared_resolutionsconcept.
Installation
npm install @opencharts/smeUsage
Define a source mapping
import { SourceMappingDefinition } from '@opencharts/sme';
const mapping = new SourceMappingDefinition({
id: 'csv-patient-v1',
version: 1,
source: { type: 'csv', system: 'epic' },
business_key: {
namespace: 'chart_chase',
type: 'Patient',
components: {
mrn: { from: 'PatientMRN', transforms: [{ name: 'trim', version: 1 }] },
},
},
shared_resolutions: [{
alias: 'patient',
resource_type: 'Patient',
resolution_profile: { id: 'epic-patient', version: 1 },
identity_parameters: {
mrn: { from: 'PatientMRN', transforms: [{ name: 'trim', version: 1 }] },
},
}],
case_resources: [{
key: 'patient',
type: 'Patient',
parameters: {
birth_date: { from: 'DOB', transforms: [{ name: 'to_iso_date', version: 1 }] },
gender: { from: 'Sex', transforms: [{ name: 'to_fhir_administrative_gender', version: 1 }] },
},
resolution: { from_shared_resolution: 'patient' },
}],
workflow: { id: 'chart-chase-v1', version: 1 },
});
mapping.validate();Register in the registry
import { SourceMappingRegistry } from '@opencharts/sme';
const registry = new SourceMappingRegistry();
registry.register(mapping);
// Retrieve by id
const def = registry.get('csv-patient-v1');
// Auto-route by source
const def2 = registry.findBySource('csv', 'epic');Apply a mapping
import { SourceMappingEngine } from '@opencharts/sme';
// normalizerRegistry from @opencharts/normalizer
// resourceValidator from @opencharts/resources (optional)
const engine = new SourceMappingEngine({ normalizerRegistry, resourceValidator });
const result = engine.apply(mapping, sourceRecord, {
tenant_id: 'tenant-001',
integration_id: 'int-001',
source_id: 'src-001',
discovery_run_id: 'run-001',
batch_id: 'batch-001',
record_key: 'row-42',
});
console.log(result.case_resources);
// [{ key: 'patient', type: 'Patient', parameters: { birth_date: '1985-01-01', gender: 'female' }, resolution: {...} }]
console.log(result.business_key);
// { namespace: 'chart_chase', type: 'Patient', components: { mrn: '12345' } }
if (result.validation) {
console.log(result.validation.valid); // true/false when resourceValidator is wired
}Binding Grammar
The SME uses a subset of the binding grammar (no concat, each, coalesce, if, select):
| Kind | Shape |
|---|---|
| from | { from: 'field', transforms?: [...] } |
| literal | { literal: value } |
| template | { template: 'text {key}' } |
| object | { object: { k: binding } } |
| array | { array: [binding, …] } |
For the full binding and condition grammar (including if, select, each, coalesce), use @opencharts/mapper.
API Reference
SourceMappingDefinition
| Member | Description |
|---|---|
| id | Unique mapping identifier |
| version | Integer ≥ 1 |
| source | { type, system } |
| business_key | { namespace, type, components } |
| shared_resolutions | Array of resolution inputs per resolvable resource |
| case_resources | Array of resource definitions |
| demand | Demand reference (passed through) |
| workflow | Workflow reference |
| validate() | Throws InvalidSourceMappingError on structural errors |
| toJSON() | Serializes to plain object |
SourceMappingRegistry
| Method | Description |
|---|---|
| register(definition) | Validate + store (immutable once published) |
| get(id, version?) | Returns definition; throws if missing |
| findBySource(type, system) | Returns definition or null |
| has(id, version?) | Returns boolean |
| list() | All registered definitions |
SourceMappingEngine
| Method | Description |
|---|---|
| apply(mapping, record, context) | Returns MappingResult |
MappingResult:
{
shared_resolutions, // [{ alias, resource_type, resolution_profile, identity_parameters, source_record_ref? }]
case_resources, // [{ key, type, parameters, resolution }]
business_key, // { namespace, type, components }
demand, // passed through from mapping
workflow, // passed through from mapping
source_record_ref, // { source_id, discovery_run_id, batch_id, record_key, classification }
validation?, // { valid, errors } — only when resourceValidator is injected
}