-
Notifications
You must be signed in to change notification settings - Fork 2
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
Add GET proposalVersionById route #1368
base: main
Are you sure you want to change the base?
Changes from all commits
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 |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from './createProposalVersion'; | ||
export * from './loadProposalVersion'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { db } from '../../db'; | ||
import { NotFoundError } from '../../../errors'; | ||
import type { JsonResultSet, ProposalVersion } from '../../../types'; | ||
|
||
export const loadProposalVersion = async ( | ||
id: number, | ||
): Promise<ProposalVersion> => { | ||
const result = await db.sql<JsonResultSet<ProposalVersion>>( | ||
'proposalVersions.selectById', | ||
{ | ||
id, | ||
}, | ||
); | ||
const proposalVersion = result.rows[0]?.object; | ||
if (proposalVersion === undefined) { | ||
throw new NotFoundError(`Entity not found`, { | ||
entityType: 'ProposalVersion', | ||
entityId: id, | ||
}); | ||
} | ||
return proposalVersion; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
SELECT proposal_version_to_json(proposal_versions.*) AS object | ||
FROM proposal_versions | ||
WHERE id = :id; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,11 +6,13 @@ | |
loadApplicationForm, | ||
loadApplicationFormField, | ||
loadProposal, | ||
loadProposalVersion, | ||
} from '../database'; | ||
import { | ||
isAuthContext, | ||
isTinyPgErrorWithQueryContext, | ||
isWritableProposalVersionWithFieldValues, | ||
isId, | ||
} from '../types'; | ||
import { | ||
DatabaseError, | ||
|
@@ -212,6 +214,30 @@ | |
}); | ||
}; | ||
|
||
const getProposalVersion = ( | ||
req: Request, | ||
res: Response, | ||
next: NextFunction, | ||
): void => { | ||
const { proposalVersionId } = req.params; | ||
if (!isId(proposalVersionId)) { | ||
next(new InputValidationError('Invalid request body.', isId.errors ?? [])); | ||
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. This is a copy pasted error (as in, the error exists in another endpoint so I totally feel for you) -- proposalVersionId is a query parameter, not part of the request body, so this error should be updated to say 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. Nice catch! |
||
return; | ||
} | ||
loadProposalVersion(proposalVersionId) | ||
.then((item) => { | ||
res.status(200).contentType('application/json').send(item); | ||
}) | ||
.catch((error: unknown) => { | ||
if (isTinyPgErrorWithQueryContext(error)) { | ||
next(new DatabaseError('Error retrieving item.', error)); | ||
return; | ||
} | ||
next(error); | ||
}); | ||
}; | ||
|
||
export const proposalVersionsHandlers = { | ||
postProposalVersion, | ||
getProposalVersion, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1823,6 +1823,51 @@ | |
} | ||
} | ||
}, | ||
"/proposalVersions/{proposalVersionId}": { | ||
"get": { | ||
"operationId": "getProposalVersionById", | ||
"summary": "Gets a specific proposalVersion.", | ||
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. Here I would say "proposal version." instead of "proposalVersion." |
||
"tags": ["Proposals"], | ||
"security": [ | ||
{ | ||
"auth": [] | ||
} | ||
], | ||
"parameters": [ | ||
{ | ||
"name": "proposalVersionId", | ||
"description": "The PDC-generated ID of a proposalVersion.", | ||
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. Here I would say "proposal version." instead of "proposalVersion." |
||
"in": "path", | ||
"required": true, | ||
"schema": { | ||
"type": "integer" | ||
} | ||
} | ||
], | ||
"responses": { | ||
"200": { | ||
"description": "The requested proposalVersion.", | ||
"content": { | ||
"application/json": { | ||
"schema": { | ||
"$ref": "#/components/schemas/ProposalVersion" | ||
} | ||
} | ||
} | ||
}, | ||
"401": { | ||
"description": "Authentication was not provided or was invalid.", | ||
"content": { | ||
"application/json": { | ||
"schema": { | ||
"$ref": "#/components/schemas/PdcError" | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
"/baseFields": { | ||
"get": { | ||
"operationId": "getBaseFields", | ||
|
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.
While this follows some of the existing conventions, and therefore I don't think my objection is reason to hold up this PR, I prefer to get the database-generated IDs explicitly rather than making the assumption that ID 1 was inserted. Something for future PRs, perhaps.
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.
Agreed, and the same can be said for the other IDs referenced here -- it's all being loaded right above so there's no cost to just
const opportunity = createOpportunity...
and then accessingopportunity.id
in the appropriate places.Also the prefix
new
here isn't contextually relevant so I'd just call itproposalVersion
ortestProposalVersion
.