Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,18 @@ To mask a property, provide an array of the properties to mask in the `construct
}
```

Alternatively, providing a string with a value of `all` in the `constructorArgs` of the Patient extractor will mask all of the supported properties listed above. The following configuration can be used to mask all properties of the `Patient` resource, rather than listing each individual property:

```bash
{
"label": "patient",
"type": "CSVPatientExtractor",
"constructorArgs": {
"filePath": "./data/patient-information.csv"
"mask": "all"
}
}
```
### Extraction Date Range

The mCODE Extraction Client will extract all data that is provided in the CSV files by default, regardless of any dates associated with each row of data. It is recommended that any required date filtering is performed outside of the scope of this client.
Expand Down
6 changes: 4 additions & 2 deletions src/extractors/CSVPatientExtractor.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@ class CSVPatientExtractor extends BaseCSVExtractor {
// 3. Generate FHIR Resources
const bundle = generateMcodeResources('Patient', packagedPatientData);

// mask fields in the patient data if specified in mask array
if (this.mask.length > 0) maskPatientData(bundle, this.mask);
// mask specified fields in the patient data
if (typeof this.mask === 'string' && this.mask === 'all') {
maskPatientData(bundle, [], true);
} else if (this.mask.length > 0) maskPatientData(bundle, this.mask);
return bundle;
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/extractors/FHIRPatientExtractor.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ class FHIRPatientExtractor extends BaseFHIRExtractor {

async get(argumentObject) {
const bundle = await super.get(argumentObject);
if (this.mask.length > 0) maskPatientData(bundle, this.mask);
// mask specified fields in the patient data
if (typeof this.mask === 'string' && this.mask === 'all') {
maskPatientData(bundle, [], true);
} else if (this.mask.length > 0) maskPatientData(bundle, this.mask);
return bundle;
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/helpers/configUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ ajv.addFormat('email-with-name', {
return emailRegex.test(email.trim().split(' ').pop());
},
});
ajv.addFormat('mask-all', {
type: 'string',
validate: (string) => string === 'all',
});

const validator = ajv.addSchema(configSchema, 'config');

Expand Down
7 changes: 5 additions & 2 deletions src/helpers/patientUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,9 @@ function getPatientName(name) {
* 'gender','mrn','name','address','birthDate','language','ethnicity','birthsex',
* 'race', 'telecom', 'multipleBirth', 'photo', 'contact', 'generalPractitioner',
* 'managingOrganization', and 'link'
* @param {Boolean} maskAll indicates that all supported fields should be masked, defaults to false
*/
function maskPatientData(bundle, mask) {
function maskPatientData(bundle, mask, maskAll = false) {
// get Patient resource from bundle
const patient = fhirpath.evaluate(
bundle,
Expand All @@ -109,7 +110,9 @@ function maskPatientData(bundle, mask) {
];
const masked = extensionArr(dataAbsentReasonExtension('masked'));

mask.forEach((field) => {
const maskingFields = maskAll ? validFields : mask;

maskingFields.forEach((field) => {
if (!validFields.includes(field)) {
throw Error(`'${field}' is not a field that can be masked. Patient will only be extracted if all mask fields are valid. Valid fields include: Valid fields include: ${validFields.join(', ')}`);
}
Expand Down
16 changes: 12 additions & 4 deletions src/helpers/schemas/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,18 @@
},
"mask": {
"title": "Masked Fields",
"type": "array",
"items": {
"type": "string"
}
"oneOf": [
{
"type": "string",
"format": "mask-all"
},
{
"type": "array",
"items": {
"type": "string"
}
}
]
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions test/helpers/patientUtils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ describe('PatientUtils', () => {
expect(bundle).toEqual(exampleMaskedPatient);
});

test('bundle should be modified to have dataAbsentReason for all fields when the maskAll flag is provided', () => {
const bundle = _.cloneDeep(examplePatient);
maskPatientData(bundle, [], true);
expect(bundle).toEqual(exampleMaskedPatient);
});

test('should mask gender even if it only had an extension', () => {
const bundle = _.cloneDeep(examplePatient);
delete bundle.entry[0].resource.gender;
Expand Down