election-tonight-client
Advanced tools
Comparing version 0.0.1-alpha.20 to 0.0.1-alpha.21
{ | ||
"name": "election-tonight-client", | ||
"version": "0.0.1-alpha.20", | ||
"version": "0.0.1-alpha.21", | ||
"main": "src/index.js", | ||
@@ -17,3 +17,2 @@ "types": "types/index.d.ts", | ||
"scripts": { | ||
"prepublishOnly": "npm run build && npm run docs", | ||
"docs:preview": "live-server ./docs", | ||
@@ -20,0 +19,0 @@ "copy:dts": "copyfiles -u 1 ./src/*.d.ts ./src/**/*.d.ts types", |
import { mergeWithReplaceArray } from '../../utils/merge.js'; | ||
import { uniq } from 'lodash-es'; | ||
@@ -13,3 +14,4 @@ export class OfficesLookup { | ||
/** | ||
* Get metadata for offices, including how offices map to jurisdictions, and metadata for the candidates running for them, by state. | ||
* Get metadata for offices, including how offices map to jurisdictions, and metadata for the candidates running for them, for each state. | ||
* The offices data for each state is organised by election type, which is useful mainly for Democratic and Republican primaries. | ||
* | ||
@@ -36,3 +38,3 @@ * @TODO | ||
* @param {import("./types").OfficesByStateOptions} options | ||
* DELETED: {Promise<import("sequelize").Model<*, *>>} | ||
* @return {Promise<import("sequelize").Model<*, *>>} | ||
*/ | ||
@@ -42,16 +44,25 @@ async getOfficesByState(states = null, options) { | ||
const defaultOptions = { | ||
State: { | ||
attributes: { exclude: ['code', 'uid', 'postalAbbr', 'name', 'fips', 'apAbbr', 'numCounties', 'numPseudoCounties'] }, | ||
}, | ||
Jurisdiction: { | ||
attributes: { exclude: ['state'] }, | ||
attributes: { exclude: ['state', 'jurisdictionType'] }, | ||
}, | ||
JurisdictionType: { | ||
attributes: { exclude: ['code'] }, | ||
}, | ||
Office: { | ||
attributes: { exclude: ['jurisdiction'] }, | ||
attributes: { exclude: ['state', 'jurisdiction'] }, | ||
}, | ||
CandidateRace: { | ||
attributes: { exclude: ['candidate', 'winner', 'finishingOrder', 'advancesToRunoff'] }, | ||
attributes: { exclude: ['candidate', 'electionType', 'winner', 'finishingOrder', 'advancesToRunoff'] }, | ||
}, | ||
ElectionType: { | ||
attributes: { exclude: ['code'] }, | ||
}, | ||
OfficeRace: { | ||
attributes: { exclude: ['office'] }, | ||
attributes: { exclude: ['office', 'electionType'] }, | ||
}, | ||
JurisdictionRace: { | ||
attributes: { exclude: ['jurisdiction'] }, | ||
attributes: { exclude: ['jurisdiction', 'electionType'] }, | ||
}, | ||
@@ -61,53 +72,69 @@ }; | ||
const queryOptions = mergeWithReplaceArray(defaultOptions, options); | ||
const officesByState = await this.db.models.State.findAll({ | ||
include: [{ | ||
model: this.db.models.Jurisdiction, | ||
...(queryOptions?.Jurisdiction || {}), | ||
separate: true, | ||
include: [ | ||
{ | ||
model: this.db.models.JurisdictionType, | ||
...(queryOptions?.JurisdictionType || {}), | ||
}, | ||
{ | ||
model: this.db.models.Office, | ||
...(queryOptions?.Office || {}), | ||
include: [ | ||
{ | ||
model: this.db.models.CandidateRace, | ||
...(queryOptions?.CandidateRace || {}), | ||
include: [{ | ||
model: this.db.models.Candidate, | ||
...(queryOptions?.Candidate || {}), | ||
const electionTypes = await this.db.models.ElectionType.findAll(); | ||
const officesByState = []; | ||
for (const electionType of electionTypes) { | ||
const { uid: electionTypeUid, name: electionTypeName } = electionType; | ||
const states = await this.db.models.State.findAll({ | ||
...(queryOptions?.State || {}), | ||
include: [{ | ||
model: this.db.models.Jurisdiction, | ||
...(queryOptions?.Jurisdiction || {}), | ||
separate: true, | ||
include: [ | ||
{ | ||
model: this.db.models.JurisdictionType, | ||
...(queryOptions?.JurisdictionType || {}), | ||
}, | ||
{ | ||
model: this.db.models.Office, | ||
...(queryOptions?.Office || {}), | ||
include: [ | ||
{ | ||
model: this.db.models.CandidateRace, | ||
where: { electionType: electionTypeUid }, | ||
...(queryOptions?.CandidateRace || {}), | ||
through: { attributes: [] }, | ||
include: [{ | ||
model: this.db.models.Candidate, | ||
...(queryOptions?.Candidate || {}), | ||
}, | ||
], | ||
}, | ||
{ | ||
model: this.db.models.ElectionType, | ||
...(queryOptions?.ElectionType || {}), | ||
model: this.db.models.OfficeRace, | ||
where: { electionType: electionTypeUid }, | ||
...(queryOptions?.OfficeRace || {}), | ||
separate: true, | ||
}], | ||
}, | ||
{ | ||
model: this.db.models.OfficeRace, | ||
...(queryOptions?.OfficeRace || {}), | ||
separate: true, | ||
include: [{ | ||
model: this.db.models.ElectionType, | ||
...(queryOptions?.ElectionType || {}), | ||
}], | ||
}], | ||
}, | ||
{ | ||
model: this.db.models.JurisdictionRace, | ||
...(queryOptions?.JurisdictionRace || {}), | ||
include: [{ | ||
model: this.db.models.ElectionType, | ||
...(queryOptions?.ElectionType || {}), | ||
}], | ||
}, | ||
], | ||
}], | ||
nest: true, | ||
}); | ||
return officesByState; | ||
}, | ||
{ | ||
model: this.db.models.JurisdictionRace, | ||
where: { electionType: electionTypeUid }, | ||
...(queryOptions?.JurisdictionRace || {}), | ||
}, | ||
], | ||
}], | ||
nest: true, | ||
}); | ||
for (const stateData of states) { | ||
const { uid: stateUid } = stateData; | ||
const stateToUpdate = officesByState.filter(d => d.state === stateUid); | ||
let instance = {}; | ||
if (stateToUpdate.length === 0) { | ||
// Initialise an instance of a state if it doesn't already exist | ||
instance.state = stateUid; | ||
instance.electionTypes = [{ name: electionTypeName, uid: electionTypeUid, offices: stateData }]; | ||
} else { | ||
instance = stateToUpdate[0]; | ||
instance.electionTypes = [...instance.electionTypes, ...[{ name: electionTypeName, uid: electionTypeUid, offices: stateData }]]; | ||
} | ||
officesByState.push(instance); | ||
} | ||
} | ||
return uniq(officesByState); | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
470456
10598