Skip to content

Commit

Permalink
Merge pull request #827 from CMSgov/QPPA-9423-add-typing-to-QPPA-9423
Browse files Browse the repository at this point in the history
QPPA-9423: Adds strong typing to index.ts
  • Loading branch information
john-manack authored Aug 27, 2024
2 parents 10d2b66 + c5d2e68 commit d7c093b
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 37 deletions.
22 changes: 22 additions & 0 deletions index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import fse from 'fs-extra';
import { vol } from 'memfs';
import path from 'path';
import YAML from 'yaml';
import * as programNamesJson from './util/program-names/program-names.json';

import * as index from './index';
import { Constants } from './constants';
Expand Down Expand Up @@ -705,4 +706,25 @@ describe('index', () => {
expect(logSpy).toBeCalledWith('mvp.json file does not exist');
});
});

// TODO - automate steps 1 and 2 below
// This test will fail when new program-names are programmatically added to ./util/program-names.json
// When this occurs, developers should:
// (1) update ./util/interfaces/program-names.ts to include the new programName
// (2) update this test to include the new programName
describe('ProgramNames interface', () => {
it('checks that the ProgramNames interface contains all program names', () => {
const programNames = Object.keys(programNamesJson).filter(obj => obj !== 'default')
expect(programNames).toStrictEqual([
'mips', 'cpcPlus', 'pcf',
'app1', 'DEFAULT', 'G0053',
'G0054', 'G0055', 'G0056',
'G0057', 'G0058', 'G0059',
'M0001', 'M0005', 'M0002',
'M0003', 'M0004', 'M1366',
'M1367', 'M1368', 'M1369',
'M1370'
]);
})
})
});
32 changes: 20 additions & 12 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ import * as fse from 'fs-extra';
import * as path from 'path';
import * as YAML from 'yaml';
import { Constants } from './constants';
import { ProgramNames } from './util/interfaces/program-names';
import { BenchmarksData } from './util/interfaces/benchmarks';
import { BenchmarksExclusionReasons } from './util/interfaces/benchmarks-exclusion-reasons';
import { CostNationalAverage } from './util/interfaces/cost-national-average';
import { Measure } from './util/interfaces/measure';
import { ClinicalCluster } from './scripts/clinical-clusters/clinical-cluster.types';
import { MVPData, MVPDataSlim } from './util/interfaces/mvp';
import { createMVPDataFile } from './util/mvp-data-utils';


Expand Down Expand Up @@ -49,16 +56,17 @@ export function updateProgramNames(performanceYear: number): void {

/**
*
* @return {ProgramNames | undefined} - program names -
* @return {ProgramNames} - program names -
* An object keyed by program name containing the current program names
*/
export function getProgramNames(): any {
export function getProgramNames(): ProgramNames {
const programNamesFilePath = path.join(__dirname, 'util/program-names', 'program-names.json');

try {
return JSON.parse(fse.readFileSync(programNamesFilePath, 'utf8'));
} catch (e) {
console.log('Error parsing the program-names.json file: ' + ' --> ' + e);
return <ProgramNames>{}
}
}

Expand All @@ -68,7 +76,7 @@ export function getProgramNames(): any {
* An object keyed by performance year with array values
* containing the benchmarks for that performance year
*/
export function getBenchmarksData(): any {
export function getBenchmarksData(): BenchmarksData {
const benchmarksByYear: any = {};

getBenchmarksYears().forEach(function (year) {
Expand Down Expand Up @@ -107,16 +115,16 @@ export function getBenchmarksSchema(performanceYear: number = Constants.currentP
* @param {number} performanceYear - The performance year to get the exclusion reasons for.
* @return {BenchmarksExclusionReasons[]} - The exclusion reasons for the given performance year.
**/
export function getBenchmarksExclusionReasons(performanceYear: number = Constants.currentPerformanceYear): any {
export function getBenchmarksExclusionReasons(performanceYear: number = Constants.currentPerformanceYear): BenchmarksExclusionReasons[] {
return JSON.parse(
fse.readFileSync(path.join(__dirname, 'benchmarks', performanceYear.toString(), 'benchmark-exclusion-reasons.json'), 'utf8'));
}

/**
* @param {number} performanceYear - The performance year to get the national averages for.
* @return {CostNationalAverages[]} - The national averages for the given performance year.
* @return {CostNationalAverage[]} - The national averages for the given performance year.
**/
export function getBenchmarksNationalAverages(performanceYear: number = Constants.currentPerformanceYear): any {
export function getBenchmarksNationalAverages(performanceYear: number = Constants.currentPerformanceYear): CostNationalAverage[] {
return JSON.parse(
fse.readFileSync(path.join(__dirname, 'benchmarks', performanceYear.toString(), 'cost-national-averages.json'), 'utf8'));
}
Expand All @@ -132,7 +140,7 @@ export function getBenchmarksNationalAveragesSchema(performanceYear: number = Co
* @param {number} performanceYear - The performance year for which to load the measures data.
* @return {Measure[]} An array of measure objects conforming to the Measure type definition.
**/
export function getMeasuresData(performanceYear: number = 2017): any {
export function getMeasuresData(performanceYear: number = 2017): Measure[] {
return JSON.parse(
fse.readFileSync(path.join(__dirname, 'measures', performanceYear.toString(), 'measures-data.json'), 'utf8'));
}
Expand All @@ -148,7 +156,7 @@ export function getMeasuresSchema(performanceYear: number = 2017): any {
* @param {number} performanceYear - The performance year for which to load the clinical cluster data.
* * @return {ClinicalCluster[]} An array of cluster objects conforming to the ClinicalCluster definition.
**/
export function getClinicalClusterData(performanceYear: number = 2017): any {
export function getClinicalClusterData(performanceYear: number = 2017): ClinicalCluster[] {
let clusterData: any[] = [];
try {
clusterData = JSON.parse(
Expand All @@ -167,9 +175,9 @@ export function getClinicalClusterSchema(performanceYear: number = 2023): any {
}

/**
* @return {any}
* @return {MVPData[]}
*/
export function getMVPData(performanceYear: number = 2023, mvpIds: string[] = []): any {
export function getMVPData(performanceYear: number = 2023, mvpIds: string[] = []): MVPData[] {
const filePath = path.join(__dirname, 'mvp', performanceYear.toString(), 'mvp-enriched.json');
let mvpData: any;

Expand All @@ -194,9 +202,9 @@ export function getMVPSchema(performanceYear: number = 2023): any {
}

/**
* @return {any}
* @return {MVPDataSlim[]}
*/
export function getMVPDataSlim(performanceYear: number = 2023): any {
export function getMVPDataSlim(performanceYear: number = 2023): MVPDataSlim[] {
const filePath = path.join(__dirname, 'mvp', performanceYear.toString(), 'mvp.json');
let mvpData: any;

Expand Down
7 changes: 4 additions & 3 deletions scripts/mvp/2023/update-mvp.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from 'fs';

import * as index from '../../../index';
import { updateProgramNames } from '../../../index';
import { createMVPDataFile } from '../../../util/mvp-data-utils';
import {
info,
warning
Expand All @@ -21,8 +22,8 @@ export function updateMvps(performanceYear: string) {
}
}

index.createMVPDataFile(Number(performanceYear));
index.updateProgramNames(Number(performanceYear));
createMVPDataFile(Number(performanceYear));
updateProgramNames(Number(performanceYear));
}

/* c8 ignore next */
Expand Down
7 changes: 4 additions & 3 deletions scripts/mvp/2024/update-mvp.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import fs from 'fs';

import * as index from '../../../index';
import {
info,
warning
} from '../../logger';
import { createMVPDataFile } from '../../../util/mvp-data-utils';
import { updateProgramNames } from '../../..';

export function updateMvps(performanceYear: string) {
const filePath = `mvp/${performanceYear}/mvp-enriched.json`;
Expand All @@ -21,8 +22,8 @@ export function updateMvps(performanceYear: string) {
}
}

index.createMVPDataFile(Number(performanceYear));
index.updateProgramNames(Number(performanceYear));
createMVPDataFile(Number(performanceYear));
updateProgramNames(Number(performanceYear));
}

/* c8 ignore next */
Expand Down
7 changes: 4 additions & 3 deletions scripts/mvp/2025/update-mvp.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import fs from 'fs';

import * as index from '../../../index';
import {
info,
warning
} from '../../logger';
import { createMVPDataFile } from '../../../util/mvp-data-utils';
import { updateProgramNames } from '../../..';

export function updateMvps(performanceYear: string) {
const filePath = `mvp/${performanceYear}/mvp-enriched.json`;
Expand All @@ -21,8 +22,8 @@ export function updateMvps(performanceYear: string) {
}
}

index.createMVPDataFile(Number(performanceYear));
index.updateProgramNames(Number(performanceYear));
createMVPDataFile(Number(performanceYear));
updateProgramNames(Number(performanceYear));
}

/* c8 ignore next */
Expand Down
33 changes: 18 additions & 15 deletions util/interfaces/benchmarks.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
export interface BenchmarksData {
[year: number]: {
measureId: string;
benchmarkYear: number;
performanceYear: number;
submissionMethod: string;
isToppedOut: boolean;
isHighPriority: boolean;
isInverse: boolean;
metricType: string;
isToppedOutByProgram: boolean;
percentiles: {
[key: string]: number;
};
averagePerformanceRate?: number;
}[];
[year: number]: BenchmarksDetails[];
}

export interface BenchmarksDetails {
measureId: string;
benchmarkYear: number;
performanceYear: number;
submissionMethod: string;
isToppedOut?: boolean;
isHighPriority?: boolean;
isInverse?: boolean;
metricType?: string;
isToppedOutByProgram?: boolean;
percentiles?: {
[key: string]: number;
};
deciles?: number[];
averagePerformanceRate?: number;
}
7 changes: 7 additions & 0 deletions util/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export { BenchmarksExclusionReasons } from './benchmarks-exclusion-reasons'
export { BenchmarksData } from './benchmarks';
export { ClinicalCluster } from './clinical-cluster';
export { CostNationalAverage } from './cost-national-average';
export { IAMeasure, PIMeasure, QualityMeasure, AggregateCostMeasure, Measure } from './measure';
export { MVPData, MVPDataSlim } from './mvp';
export { ProgramNames } from './program-names';
30 changes: 30 additions & 0 deletions util/interfaces/mvp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { AggregateCostMeasure, IAMeasure, PIMeasure, QualityMeasure } from "./measure";

export interface BaseMVP {
mvpId: string;
clinicalTopic: string;
title: string;
description: string;
specialtiesMostApplicableTo: string[];
clinicalTopics: string;
hasCahps: boolean;
hasOutcomeAdminClaims: boolean;
}

export interface MVPData extends BaseMVP {
qualityMeasures: QualityMeasure[];
iaMeasures: IAMeasure[];
costMeasures: AggregateCostMeasure[];
foundationPiMeasures: PIMeasure[];
foundationQualityMeasures: QualityMeasure[];
administrativeClaimsMeasures: QualityMeasure[];
}

export interface MVPDataSlim extends BaseMVP {
qualityMeasures: string[];
iaMeasures: string[];
costMeasures: string[];
foundationPiMeasures: string[];
foundationQualityMeasures: string[];
administrativeClaimsMeasures: string[];
}
23 changes: 22 additions & 1 deletion util/interfaces/program-names.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,25 @@
// Define the interface for program names
export interface ProgramNames {
[key: string]: string;
"mips": "mips",
"cpcPlus": "cpcPlus",
"pcf": "pcf",
"app1": "app1",
"DEFAULT": "mips",
"G0053": "G0053",
"G0054": "G0054",
"G0055": "G0055",
"G0056": "G0056",
"G0057": "G0057",
"G0058": "G0058",
"G0059": "G0059",
"M0001": "M0001",
"M0005": "M0005",
"M0002": "M0002",
"M0003": "M0003",
"M0004": "M0004",
"M1366": "M1366",
"M1367": "M1367",
"M1368": "M1368",
"M1369": "M1369",
"M1370": "M1370"
}

0 comments on commit d7c093b

Please sign in to comment.