Skip to content

Commit

Permalink
Add oneOf support to OpenAPI generator
Browse files Browse the repository at this point in the history
Used for Rust enums with struct data.

This also removes the unused `DataEntryStatus` type from the OpenAPI
spec and fixes the build without the `dev-database` feature by always
including the `ElectionRequest` struct.
  • Loading branch information
praseodym authored and Lionqueen94 committed Jan 21, 2025
1 parent 05a76d7 commit f31ae6c
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 240 deletions.
210 changes: 0 additions & 210 deletions backend/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1219,114 +1219,6 @@
}
}
},
"DataEntryStatus": {
"oneOf": [
{
"type": "object",
"required": [
"status"
],
"properties": {
"status": {
"type": "string",
"enum": [
"FirstEntryNotStarted"
]
}
}
},
{
"type": "object",
"required": [
"state",
"status"
],
"properties": {
"state": {
"$ref": "#/components/schemas/FirstEntryInProgress"
},
"status": {
"type": "string",
"enum": [
"FirstEntryInProgress"
]
}
}
},
{
"type": "object",
"required": [
"state",
"status"
],
"properties": {
"state": {
"$ref": "#/components/schemas/SecondEntryNotStarted"
},
"status": {
"type": "string",
"enum": [
"SecondEntryNotStarted"
]
}
}
},
{
"type": "object",
"required": [
"state",
"status"
],
"properties": {
"state": {
"$ref": "#/components/schemas/SecondEntryInProgress"
},
"status": {
"type": "string",
"enum": [
"SecondEntryInProgress"
]
}
}
},
{
"type": "object",
"required": [
"state",
"status"
],
"properties": {
"state": {
"$ref": "#/components/schemas/EntriesDifferent"
},
"status": {
"type": "string",
"enum": [
"EntriesDifferent"
]
}
}
},
{
"type": "object",
"required": [
"state",
"status"
],
"properties": {
"state": {
"$ref": "#/components/schemas/Definitive"
},
"status": {
"type": "string",
"enum": [
"Definitive"
]
}
}
}
]
},
"DataEntryStatusName": {
"type": "string",
"enum": [
Expand All @@ -1338,17 +1230,6 @@
"definitive"
]
},
"Definitive": {
"type": "object",
"required": [
"finished_at"
],
"properties": {
"finished_at": {
"type": "string"
}
}
},
"DifferencesCounts": {
"type": "object",
"description": "Differences counts, part of the polling station results.",
Expand Down Expand Up @@ -1638,21 +1519,6 @@
}
}
},
"EntriesDifferent": {
"type": "object",
"required": [
"first_entry",
"second_entry"
],
"properties": {
"first_entry": {
"$ref": "#/components/schemas/PollingStationResults"
},
"second_entry": {
"$ref": "#/components/schemas/PollingStationResults"
}
}
},
"ErrorReference": {
"type": "string",
"description": "Error reference used to show the corresponding error message to the end-user",
Expand Down Expand Up @@ -1701,31 +1567,6 @@
}
}
},
"FirstEntryInProgress": {
"type": "object",
"required": [
"progress",
"first_entry",
"client_state"
],
"properties": {
"client_state": {
"type": "object",
"description": "Client state for the data entry (arbitrary JSON)"
},
"first_entry": {
"$ref": "#/components/schemas/PollingStationResults",
"description": "Data entry for a polling station"
},
"progress": {
"type": "integer",
"format": "int32",
"description": "Data entry progress between 0 and 100",
"maximum": 100,
"minimum": 0
}
}
},
"GetDataEntryResponse": {
"type": "object",
"description": "Response structure for getting data entry of polling station results",
Expand Down Expand Up @@ -2131,57 +1972,6 @@
}
}
},
"SecondEntryInProgress": {
"type": "object",
"required": [
"finalised_first_entry",
"first_entry_finished_at",
"progress",
"second_entry",
"client_state"
],
"properties": {
"client_state": {
"type": "object",
"description": "Client state for the data entry (arbitrary JSON)"
},
"finalised_first_entry": {
"$ref": "#/components/schemas/PollingStationResults",
"description": "Data entry for a polling station"
},
"first_entry_finished_at": {
"type": "string",
"description": "When the first entry was finalised"
},
"progress": {
"type": "integer",
"format": "int32",
"description": "Data entry progress between 0 and 100",
"maximum": 100,
"minimum": 0
},
"second_entry": {
"$ref": "#/components/schemas/PollingStationResults",
"description": "Data entry for a polling station"
}
}
},
"SecondEntryNotStarted": {
"type": "object",
"required": [
"finalised_first_entry",
"first_entry_finished_at"
],
"properties": {
"finalised_first_entry": {
"$ref": "#/components/schemas/PollingStationResults",
"description": "Data entry for a polling station"
},
"first_entry_finished_at": {
"type": "string"
}
}
},
"ValidationResult": {
"type": "object",
"required": [
Expand Down
1 change: 0 additions & 1 deletion backend/src/election/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ pub struct Election {

/// Election request
#[derive(Serialize, Deserialize, ToSchema, Clone, Debug)]
#[cfg(feature = "dev-database")]
pub struct ElectionRequest {
pub name: String,
pub location: String,
Expand Down
1 change: 0 additions & 1 deletion backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ pub fn create_openapi() -> utoipa::openapi::OpenApi {
data_entry::GetDataEntryResponse,
data_entry::DifferencesCounts,
data_entry::PoliticalGroupVotes,
data_entry::status::DataEntryStatus,
data_entry::status::DataEntryStatusName,
data_entry::PollingStationResults,
data_entry::VotersCounts,
Expand Down
30 changes: 2 additions & 28 deletions frontend/lib/api/gen/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,6 @@ export type DataEntryStatusName =
| "entries_different"
| "definitive";

export interface Definitive {
finished_at: string;
}

/**
* Differences counts, part of the polling station results.
*/
Expand Down Expand Up @@ -266,11 +262,6 @@ export interface ElectionStatusResponseEntry {
status: DataEntryStatusName;
}

export interface EntriesDifferent {
first_entry: PollingStationResults;
second_entry: PollingStationResults;
}

/**
* Error reference used to show the corresponding error message to the end-user
*/
Expand Down Expand Up @@ -307,12 +298,6 @@ export interface ErrorResponse {
reference: ErrorReference;
}

export interface FirstEntryInProgress {
client_state: unknown;
first_entry: PollingStationResults;
progress: number;
}

/**
* Response structure for getting data entry of polling station results
*/
Expand Down Expand Up @@ -431,26 +416,15 @@ export interface PollingStationResults {
*/
export type PollingStationType = "FixedLocation" | "Special" | "Mobile";

export type RestSeatAllocationDetails = Lt19SeatsAllocation | Gte19SeatsAllocation;

/**
* Response structure for saving data entry of polling station results
*/
export interface SaveDataEntryResponse {
validation_results: ValidationResults;
}

export interface SecondEntryInProgress {
client_state: unknown;
finalised_first_entry: PollingStationResults;
first_entry_finished_at: string;
progress: number;
second_entry: PollingStationResults;
}

export interface SecondEntryNotStarted {
finalised_first_entry: PollingStationResults;
first_entry_finished_at: string;
}

export interface ValidationResult {
code: ValidationResultCode;
fields: string[];
Expand Down
12 changes: 12 additions & 0 deletions frontend/scripts/openapi/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,18 @@ function addDefinition(name: string, v: ReferenceObject | SchemaObject) {
if (v.enum) {
result.push(`export type ${name} = ${v.enum.map((e) => `"${e}"`).join(" | ")};`);
}
} else if (v.oneOf) {
const types: string[] = [];
for (const obj of v.oneOf) {
if ("properties" in obj && obj.properties) {
for (const property of Object.values(obj.properties)) {
if ("$ref" in property) {
types.push(property.$ref.substring(property.$ref.lastIndexOf("/") + 1));
}
}
}
}
result.push(`export type ${name} = ${types.join(" | ")};`);
}

return result.join("\n");
Expand Down

0 comments on commit f31ae6c

Please sign in to comment.