transform
— Manipulate Data
Transform Flows are used to manipulate message data.
Interface
The interface TransformFlow can be defined as:
type TransformFunc = (msg: IMsg, context: IMessageContext) => IMsg
type TransformFlow =
| TransformFunc
| { kind: 'transform'; transform: TransformFunc }
Refer to the Message Interface for more information on the IMsg
exposed methods and transforming the data in the message.
Refer to the Context Object for more information on the IMessageContext
type.
The transformer functions of the class retuns back the class instance, so you can chain them together.
Use Case
The Ingestion and Route each allow for an array of flows. The transform flow, is one of the allowed flows in either one of these arrays. If a message is transformed in an ingestion flow, then all of the latter flows in the ingestion, and all of the routes will use the newly transformed data. If a message is transformed in a route, then only the latter flows in that route will use the newly transformed data. Routes are called asynchronously, The Ingestion flows are called synchronously.
const channel: ChannelConfig = {
// ...
ingestion: [
// transformers here
],
routes: [
{
kind: 'route',
name: 'Route 1',
flows: [
// transformers here
],
},
{
kind: 'route',
name: 'Route 2',
flows: [
// transformers here
],
}
]
};
Example
Here is an example of a transformer that takes the field PV1-3 and adds a prefix to it:
import gofer, { ChannelConfig, TransformFunc } from '@gofer-engine/engine';
const transform: TransformFunc = (msg) =>
msg.map('PV1-3[1].1', <T>(location: T) => `HOSP.${location}` as T);
// OOP style
gofer.listen('tcp', 'localhost', 5515)
.name('Hosp Location Channel with OOP')
.transform(transform)
.ack()
// Config style
const channelConfig: ChannelConfig = {
name: 'Hosp Location Channel with Configs',
source: {
kind: 'tcp',
tcp: {
host: 'localhost',
port: 5516,
},
},
ingestion: [{
kind: 'transform',
transform,
}],
};
gofer.configs([channelConfig]);
Advanced Example
Since Gofer Engine uses native TypeScript/JavaScript, you can use any of the recipes you are familiar with to pass variables and create advanced transformer logic. You could even keep your transformers in a common directory and import them where needed into your channels.
Let's refactor the previous example a little bit and make the transformer function reusable for other paths and allowing a passed through prefix/suffix.
import { TransformFunc } from '@gofer-engine/engine';
export const addPrefix =
(path: string, prefix?: string): TransformFunc =>
(msg) =>
msg.map(
path,
<T>(value: T) => `${prefix ?? ''}${value}` as T,
);
import gofer from '@gofer-engine/engine';
import { addPrefix } from './addPrefix';
gofer
.schedule(
'HL7v2',
{
second: 0,
minute: 15,
},
true,
)
.file({
directory: '//fileshare/your_directory',
filterOptions: {
filenameRegex: '*\\.hl7$',
fileAgeMinMS: 1000,
ignoreDotFiles: true,
}
})
.routes((route) => [
route()
.transform(addPrefix('PID-18.1', 'H'))
.send('tcp', 'emr.example.com', 5517),
route()
.transform(addPrefix('PID.18-1', 'L'))
.send('https', {
host: 'lab.example.com',
port: 443,
path: '/api/adt-feed',
method: 'POST',
basicAuth: {
username: 'gofer-service',
password: 'gofer-service-password',
}
})
]);```
Advanced Type Control
For advanced type control, you can pass through a generic to the ChannelConfig
(the second generic option) which passes down to the FilterFlow
generic to either:
'F'
= Only allows raw transform functions. E.G.ingestion: [(msg) => msg]
'O'
= Only allow transforming functions in objects. E.G.ingestion: [{ transform: (msg) => msg }]
'B'
= Allow Both raw transform functions or wrapped in objects. E.G.ingestion: [(msg) => msg, { transform: (msg) => msg }]
The default is 'B'. E.G.const conf: ChannelConfig<'B', 'B'> = ...
OOP Style
The OOP style channel builder transform method aligns with the following types:
IngestionClass.transform = (transform: TransformFlow<'F'>) => IngestionClass
RouteClass.transform = (transform: TransformFlow<'F>) => RouteClass
This means that the transform
method accepts a single argument which is a function.