-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
VACMS-16638: Static-Data-File Generation (KISS) #335
Changes from all commits
e1a0a0e
5485979
1c0ddf4
3cde4b9
104d373
560c421
ceabd16
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { QueryData, QueryFormatter, QueryParams } from 'next-drupal-query' | ||
import { queries } from '.' | ||
import { RESOURCE_TYPES } from '@/lib/constants/resourceTypes' | ||
import { fetchAndConcatAllResourceCollectionPages } from '@/lib/drupal/query' | ||
import { VamcEhr as DrupalVamcEhr } from '@/types/drupal/vamcEhr' | ||
import { VamcEhrGraphQLMimic } from '@/types/formatted/vamcEhr' | ||
import { PAGE_SIZES } from '@/lib/constants/pageSizes' | ||
|
||
const PAGE_SIZE = PAGE_SIZES.MAX | ||
|
||
// Define the query params for fetching node--health_care_local_facility. | ||
export const params: QueryParams<null> = () => { | ||
return queries | ||
.getParams() | ||
.addFields(RESOURCE_TYPES.VAMC_FACILITY, [ | ||
'title', | ||
'field_facility_locator_api_id', | ||
'field_region_page', | ||
]) | ||
.addFilter('field_main_location', '1') | ||
.addInclude(['field_region_page']) | ||
.addFields(RESOURCE_TYPES.VAMC_SYSTEM, ['title', 'field_vamc_ehr_system']) | ||
} | ||
|
||
// Implement the data loader. | ||
export const data: QueryData<null, DrupalVamcEhr[]> = async (): Promise< | ||
DrupalVamcEhr[] | ||
> => { | ||
const { data } = | ||
await fetchAndConcatAllResourceCollectionPages<DrupalVamcEhr>( | ||
RESOURCE_TYPES.VAMC_FACILITY, | ||
params(), | ||
PAGE_SIZE | ||
) | ||
return data | ||
} | ||
|
||
export const formatter: QueryFormatter<DrupalVamcEhr[], VamcEhrGraphQLMimic> = ( | ||
entities: DrupalVamcEhr[] | ||
) => { | ||
// For now, return data formatted as it is in content-build (mimic GraphQL output). | ||
// In future, we should move the formatting from the preProcess in vets-website | ||
// into this formatter and, while it exists, into postProcess in content-build. | ||
// This change will require a coordinated effort so as to not break things with regard | ||
// to what vets-website is expecting and what is present in the generated file. | ||
return { | ||
data: { | ||
nodeQuery: { | ||
count: entities.length, | ||
entities: entities.map((entity) => ({ | ||
title: entity.title, | ||
fieldFacilityLocatorApiId: entity.field_facility_locator_api_id, | ||
fieldRegionPage: { | ||
entity: { | ||
title: entity.field_region_page.title, | ||
fieldVamcEhrSystem: | ||
entity.field_region_page.field_vamc_ehr_system, | ||
}, | ||
}, | ||
})), | ||
}, | ||
}, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,6 @@ | ||
import { | ||
RESOURCE_TYPES, | ||
ADDITIONAL_RESOURCE_TYPES, | ||
} from '@/lib/constants/resourceTypes' | ||
import { RESOURCE_TYPES } from '@/lib/constants/resourceTypes' | ||
|
||
export const PAGE_SIZES = { | ||
[RESOURCE_TYPES.STORY_LISTING]: 10, | ||
[ADDITIONAL_RESOURCE_TYPES.STATIC_PATHS]: 50, //must be <= 50 due to JSON:API limit | ||
MAX: 50, //50 is JSON:API limit. Use this for fetching as many as possible at a time. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. love this |
||
} as const |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { | ||
GetStaticPathsContext, | ||
GetStaticPathsResult, | ||
GetStaticPropsContext, | ||
} from 'next' | ||
import fs from 'fs' | ||
import path from 'path' | ||
import { QueryDataOptsMap, queries } from '@/data/queries' | ||
|
||
type StaticJsonFile<T extends keyof QueryDataOptsMap> = { | ||
filename: string | ||
query: T | ||
queryOpts?: QueryDataOptsMap[T] | ||
} | ||
|
||
const STATIC_JSON_FILES: Array<StaticJsonFile<keyof QueryDataOptsMap>> = [ | ||
{ | ||
filename: 'vamc-ehr', | ||
query: 'vamc-ehr', | ||
} as StaticJsonFile<'vamc-ehr'>, | ||
|
||
// Another example: | ||
// { | ||
// filename: 'hypothetical-banner-data-static-json-file', | ||
// query: 'banner-data', //must be defined in QUERIES_MAP in src/data/queries/index.ts | ||
// queryOpts: { | ||
// itemPath: 'path/to/item', | ||
// }, | ||
// } as StaticJsonFile<'banner-data'>, | ||
] | ||
|
||
/* This component never generates a page, but this default export must be present */ | ||
export default function StaticJsonPage() { | ||
return null | ||
} | ||
|
||
export async function getStaticPaths( | ||
context: GetStaticPathsContext | ||
): Promise<GetStaticPathsResult> { | ||
if (process.env.SSG === 'false') { | ||
return { | ||
paths: [], | ||
fallback: 'blocking', | ||
} | ||
} | ||
|
||
return { | ||
paths: STATIC_JSON_FILES.map(({ filename }) => ({ | ||
params: { | ||
filename, | ||
}, | ||
})), | ||
fallback: 'blocking', | ||
} | ||
} | ||
|
||
export async function getStaticProps(context: GetStaticPropsContext) { | ||
const staticJsonFilename = context.params?.filename | ||
const staticJsonFile = STATIC_JSON_FILES.find( | ||
({ filename }) => filename === staticJsonFilename | ||
) | ||
if (staticJsonFile) { | ||
const { filename, query, queryOpts = {} } = staticJsonFile | ||
|
||
// fetch data | ||
const data = await queries.getData(query, queryOpts) | ||
|
||
// Write to /public/data/cms | ||
const filePath = path.resolve(`public/data/cms/${filename}.json`) | ||
const directoryPath = path.dirname(filePath) | ||
if (!fs.existsSync(directoryPath)) { | ||
fs.mkdirSync(directoryPath, { | ||
recursive: true, | ||
}) | ||
} | ||
fs.writeFileSync(filePath, JSON.stringify(data)) | ||
} | ||
return { | ||
notFound: true, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Noting that this 404 only triggers if someone visits |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export type VamcEhr = { | ||
title: string | ||
field_facility_locator_api_id: string | ||
field_region_page: { | ||
title: string | ||
field_vamc_ehr_system: 'vista' | 'cerner' | 'cerner_staged' | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// // FUTURE USE | ||
// // vamc-ehr.json should eventually include formatted data. | ||
// // At the least, it should contain formatted facilities. | ||
// export type VamcEhrFacility = { | ||
// title: string | ||
// vhaId: string | ||
// vamcFacilityName: string | ||
// vamcSystemName: string | ||
// ehr: 'vista' | 'cerner' | 'cerner_staged' | ||
// } | ||
// // Maybe addtionally, it should categorize the | ||
// // facilities and offload this piece from vets-website code as well. | ||
// export type VamcEhr = { | ||
// ehrDataByVhaId: { | ||
// vhaId: VamcEhrFacility, | ||
// }, | ||
// cernerFacilities: VamcEhrFacility[], | ||
// vistaFacilities: VamcEhrFacility[], | ||
// } | ||
|
||
export type VamcEhrGraphQLEntity = { | ||
title: string | ||
fieldFacilityLocatorApiId: string | ||
fieldRegionPage: { | ||
entity: { | ||
title: string | ||
fieldVamcEhrSystem: 'vista' | 'cerner' | 'cerner_staged' | ||
} | ||
} | ||
} | ||
|
||
export type VamcEhrGraphQLMimic = { | ||
data: { | ||
nodeQuery: { | ||
count: number | ||
entities: VamcEhrGraphQLEntity[] | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
completely agree with this callout, but i am kind of thinking the "future" state should not happen until w/e page type(s) that use this data have been ported to next-build. avoids the most potential drift and eases the coordinated effort back to 2 repos.