-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #40 from azavea/ms/add-spending-fetch-script
Add spending and state data fetching scripts
- Loading branch information
Showing
17 changed files
with
297 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#!/bin/bash | ||
|
||
USAGE="Fetch and save spending data" | ||
|
||
source ./scripts/_sourced | ||
check_for_help_flag "$@" | ||
|
||
./scripts/yarn run fetch-data |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,3 +21,5 @@ | |
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
/src/data |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { mkdir } from 'node:fs/promises'; | ||
import { existsSync } from 'node:fs'; | ||
|
||
import { dataDir } from './nodeConstants'; | ||
|
||
import fetchPerCapitaSpendingData from './fetchPerCapitaSpendingData'; | ||
import fetchStatesData from './fetchStatesData'; | ||
|
||
async function fetchData() { | ||
if (!existsSync(dataDir)) { | ||
await mkdir(dataDir); | ||
} | ||
|
||
await Promise.all([fetchStatesData(), fetchPerCapitaSpendingData()]); | ||
} | ||
|
||
fetchData(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import fs from 'node:fs/promises'; | ||
import { existsSync } from 'node:fs'; | ||
|
||
import path from 'node:path'; | ||
|
||
import { spendingApiUrl } from '../src/constants'; | ||
import { Category } from '../src/enums'; | ||
import { | ||
getAgenciesForCategory, | ||
getDefaultSpendingByGeographyRequest, | ||
} from '../src/util'; | ||
|
||
import { dataDir } from './nodeConstants'; | ||
import httpsRequestToFile from './httpRequestToFile'; | ||
|
||
export default async function fetchPerCapitaSpendingData() { | ||
console.log('Fetching per-capita spending data...'); | ||
|
||
await Promise.all([ | ||
writeSpendingDataFile(), | ||
writeSpendingDataFile(Category.CLIMATE), | ||
writeSpendingDataFile(Category.CIVIL_WORKS), | ||
writeSpendingDataFile(Category.TRANSPORTATION), | ||
writeSpendingDataFile(Category.BROADBAND), | ||
writeSpendingDataFile(Category.OTHER), | ||
]); | ||
} | ||
|
||
async function writeSpendingDataFile(category?: Category) { | ||
const filename = path.join(dataDir, `${category ?? 'all'}.spending.json`); | ||
|
||
if (existsSync(filename)) { | ||
console.warn( | ||
` Skipping ${ | ||
category ?? 'All' | ||
} spending because the file already exists.` | ||
); | ||
return; | ||
} | ||
|
||
const requestBody = getDefaultSpendingByGeographyRequest(); | ||
|
||
if (category) { | ||
requestBody.filters.agencies = getAgenciesForCategory(category); | ||
} | ||
|
||
return fs.open(filename, 'w').then(async fileHandle => { | ||
await httpsRequestToFile({ | ||
url: `${spendingApiUrl}/search/spending_by_geography/`, | ||
fileHandle, | ||
options: { | ||
method: 'POST', | ||
}, | ||
body: JSON.stringify(requestBody), | ||
}); | ||
|
||
fileHandle.close(); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import fs from 'node:fs/promises'; | ||
import { existsSync } from 'node:fs'; | ||
import path from 'node:path'; | ||
|
||
import { spendingApiUrl } from '../src/constants'; | ||
|
||
import { dataDir } from './nodeConstants'; | ||
import httpsRequestToFile from './httpRequestToFile'; | ||
|
||
export default async function fetchStatesData() { | ||
console.log('Fetching state data...'); | ||
|
||
const filename = path.join(dataDir, 'states.json'); | ||
|
||
if (existsSync(filename)) { | ||
console.warn(' Skipping states data because the file already exists.'); | ||
return; | ||
} | ||
|
||
await fs.open(filename, 'w').then(async fileHandle => { | ||
await httpsRequestToFile({ | ||
url: `${spendingApiUrl}/recipient/state/`, | ||
fileHandle, | ||
}); | ||
|
||
fileHandle.close(); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { FileHandle } from 'node:fs/promises'; | ||
import https from 'node:https'; | ||
|
||
export default function httpsRequestToFile({ | ||
url, | ||
fileHandle, | ||
options = {}, | ||
body, | ||
}: { | ||
url: string; | ||
fileHandle: FileHandle; | ||
options?: https.RequestOptions; | ||
body?: string; | ||
}): Promise<void> { | ||
return new Promise((resolve, reject) => { | ||
const request = https.request( | ||
url, | ||
{ | ||
headers: { | ||
'Content-Type': 'application/json', | ||
...(options.headers ?? {}), | ||
}, | ||
...options, | ||
}, | ||
response => { | ||
response.on('data', data => { | ||
fileHandle.write(data); | ||
}); | ||
|
||
response.on('end', () => { | ||
resolve(); | ||
}); | ||
} | ||
); | ||
|
||
request.on('error', error => reject(error)); | ||
|
||
if (body) { | ||
request.write(body); | ||
} | ||
|
||
request.end(); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import path from 'node:path'; | ||
|
||
export const dataDir = path.join(__dirname, '..', 'src', 'data'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import { FetchArgs, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; | ||
|
||
import { | ||
SpendingByGeographyRequest, | ||
SpendingByGeographyResponse, | ||
} from './types/api'; | ||
import { getCategoryForAgencies } from './util'; | ||
import { Category } from './enums'; | ||
|
||
import states from './data/states.json'; | ||
import allSpending from './data/all.spending.json'; | ||
import broadbandSpending from './data/Broadband.spending.json'; | ||
import civilWorksSpending from './data/Civil Works.spending.json'; | ||
import climateSpending from './data/Climate.spending.json'; | ||
import otherSpending from './data/Other.spending.json'; | ||
import transportationSpending from './data/Transportation.spending.json'; | ||
|
||
const cachedApiQuery: typeof fetchBaseQuery = _ => { | ||
return (stringOrArgs, api) => { | ||
const args = isFetchArgs(stringOrArgs) | ||
? stringOrArgs | ||
: { url: stringOrArgs }; | ||
|
||
switch (args.url) { | ||
case '/recipient/state/': | ||
return wrapIntoData(getStates()); | ||
case '/search/spending_by_geography/': | ||
return wrapIntoData( | ||
getSpendingByGeography( | ||
args.body as SpendingByGeographyRequest | ||
) | ||
); | ||
|
||
default: | ||
throw new Error(`Unknown url: ${args.url}`); | ||
} | ||
}; | ||
}; | ||
|
||
function isFetchArgs(args: string | FetchArgs): args is FetchArgs { | ||
return typeof args !== 'string'; | ||
} | ||
|
||
function wrapIntoData<T>(response: T): { data: T } { | ||
return { data: response }; | ||
} | ||
|
||
function getStates() { | ||
return states; | ||
} | ||
|
||
function getSpendingByGeography( | ||
request: SpendingByGeographyRequest | ||
): SpendingByGeographyResponse { | ||
const category = request.filters.agencies | ||
? getCategoryForAgencies(request.filters.agencies) | ||
: undefined; | ||
|
||
const spending = category | ||
? getSpendingForCategory(category) | ||
: (allSpending as SpendingByGeographyResponse); | ||
|
||
if (request.geo_layer_filters) { | ||
return { | ||
...spending, | ||
results: spending.results.filter(result => | ||
request.geo_layer_filters!.includes(result.shape_code) | ||
), | ||
}; | ||
} | ||
|
||
return spending; | ||
} | ||
|
||
function getSpendingForCategory( | ||
category: Category | ||
): SpendingByGeographyResponse { | ||
switch (category) { | ||
case Category.BROADBAND: | ||
return broadbandSpending as SpendingByGeographyResponse; | ||
case Category.CIVIL_WORKS: | ||
return civilWorksSpending as SpendingByGeographyResponse; | ||
case Category.CLIMATE: | ||
return climateSpending as SpendingByGeographyResponse; | ||
case Category.OTHER: | ||
return otherSpending as SpendingByGeographyResponse; | ||
case Category.TRANSPORTATION: | ||
return transportationSpending as SpendingByGeographyResponse; | ||
} | ||
} | ||
|
||
export default cachedApiQuery; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters