Skip to content

Commit

Permalink
feature: migrate remaining HttpExceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Carlson committed Dec 17, 2024
1 parent ba48d7d commit 5ecb56e
Show file tree
Hide file tree
Showing 11 changed files with 38 additions and 51 deletions.
3 changes: 2 additions & 1 deletion packages/app/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"extends": "next/core-web-vitals",
"rules": {
"react-hooks/exhaustive-deps": "off"
"react-hooks/exhaustive-deps": "off",
"@next/next/no-html-link-for-pages": 1
}
}
4 changes: 2 additions & 2 deletions packages/app/documents/service.legacy.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import cloneDeep from 'lodash.clonedeep'
import createError from 'http-errors'
import log from '../lib/log'
import { getDocumentsDbLegacy } from './db.legacy'

Expand Down Expand Up @@ -149,8 +150,7 @@ async function legacyHandleModelChanges(document: Document) {
} catch (error) {
log.error(error)

throw new HttpException(
ErrorCode.InternalServerError,
throw new createError.InternalServerError(
`Updating state history for ${document.name} failed.`
)
}
Expand Down
32 changes: 11 additions & 21 deletions packages/app/documents/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,7 @@ export async function getDocument(
)

if (!document) {
throw new HttpException(
ErrorCode.NotFound,
throw new createError.NotFound(
`Requested document, ${documentTitle}, in model, ${modelName}, was not found`
)
}
Expand Down Expand Up @@ -326,10 +325,7 @@ export async function cloneDocument(
): Promise<ErrorData<Document>> {
try {
if (!user) {
throw new HttpException(
ErrorCode.Unauthorized,
'User is not authenticated'
)
throw new createError.Unauthorized('User is not authenticated')
}

const documentsDb = await getDocumentsDb()
Expand Down Expand Up @@ -362,8 +358,7 @@ export async function cloneDocument(
)

if (newDocumentAlreadyExists) {
throw new HttpException(
ErrorCode.BadRequest,
throw new createError.BadRequest(
`A document already exists with the title: '${newDocument[titleProperty]}'`
)
}
Expand Down Expand Up @@ -442,7 +437,7 @@ export async function patchDocument(
const [patchErrors, patchedDocument] = jsonPatch(existingDocument, operations)

if (patchErrors) {
throw new HttpException(ErrorCode.BadRequest, patchErrors.message)
throw new createError.BadRequest(patchErrors.message)
}

// all operations successfully made, save to db as a new document
Expand Down Expand Up @@ -474,11 +469,11 @@ export async function changeDocumentState(
): Promise<ErrorData<Document>> {
try {
if (!newState) {
throw new HttpException(ErrorCode.BadRequest, 'No state provided')
throw new createError.BadRequest('No state provided')
}

if (!user) {
throw new HttpException(ErrorCode.Unauthorized, 'User is not logged in')
throw new createError.Unauthorized('User is not logged in')
}

const documentsDb = await getDocumentsDb()
Expand Down Expand Up @@ -640,32 +635,28 @@ export async function constructNewDocumentState(

//! can't transition to a state the document is already in
if (newState === document['x-meditor'].state) {
throw new HttpException(
ErrorCode.BadRequest,
throw new createError.BadRequest(
`Cannot transition to state [${newState}] as the document is in this state already`
)
}

//! can't transition to a state that isn't in the workflow
if (targetStates.indexOf(newState) < 0) {
throw new HttpException(
ErrorCode.BadRequest,
throw new createError.BadRequest(
`Cannot transition to state [${newState}] as it is not a valid state in the workflow`
)
}

//! can't transition to a state the user does not have permission to transition to
if (document['x-meditor'].targetStates.indexOf(newState) < 0) {
throw new HttpException(
ErrorCode.BadRequest,
throw new createError.BadRequest(
`User does not have the permissions to transition to state ${newState}.`
)
}

//! can't transition if the workflow has two edges with the same source and same target (how do we know which edge to follow?)
if (matchingEdges.length !== 1) {
throw new HttpException(
ErrorCode.InternalServerError,
throw new createError.InternalServerError(
`Workflow, ${model.workflow.name}, is misconfigured! There are duplicate edges from '${document['x-meditor'].state}' to '${newState}'.`
)
}
Expand Down Expand Up @@ -899,8 +890,7 @@ export async function strictValidateDocument(

//* Unlike most use-cases, we don't want to throw for a validation error; we just return it.
if (errors.length) {
const validationError = new HttpException(
ErrorCode.ValidationError,
const validationError = new createError.ValidationError(
`Document "${
documentToValidate[titleProperty]
}" does not validate against the schema for model "${modelName}": ${JSON.stringify(
Expand Down
7 changes: 3 additions & 4 deletions packages/app/macros/service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import cloneDeep from 'lodash.clonedeep'
import createError from 'http-errors'
import log from '../lib/log'
import { getMacrosDb } from './db'
import type { ErrorData } from '../declarations'
Expand Down Expand Up @@ -26,17 +27,15 @@ async function runModelTemplates(
const macroService = macros.get(macroName)

if (!macroService) {
throw new HttpException(
ErrorCode.BadRequest,
throw new createError.BadRequest(
`Macro, ${macroName}, not supported.`
)
}

const [error, filledTemplate] = await macroService(macroArgument)

if (error) {
throw new HttpException(
ErrorCode.InternalServerError,
throw new createError.InternalServerError(
`Template macro ${macroName} did not run.`
)
}
Expand Down
11 changes: 4 additions & 7 deletions packages/app/models/service.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import createError from 'http-errors'
import jsonpath from 'jsonpath'
import log from '../lib/log'
import { getDocumentsDb } from '../documents/db'
Expand Down Expand Up @@ -33,25 +34,21 @@ export async function getModel(
): Promise<ErrorData<Model>> {
try {
if (!modelName) {
throw new HttpException(ErrorCode.BadRequest, 'Model name is required')
throw new createError.BadRequest('Model name is required')
}

const modelsDb = await getModelsDb()
const model = await modelsDb.getModel(modelName)

if (!model) {
throw new HttpException(
ErrorCode.NotFound,
`Model not found: ${modelName}`
)
throw new createError.NotFound(`Model not found: ${modelName}`)
}

// see top level documentation for description of macro templates
if (options.populateMacroTemplates) {
// validate the model's schema before continuing
if (!isJson(model.schema)) {
throw new HttpException(
ErrorCode.BadRequest,
throw new createError.BadRequest(
`The schema for model, ${modelName}, contains invalid JSON`
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@ import {
getCommentForDocument,
updateCommentAsUser,
} from '../../../../../../../../comments/service'
import {
apiError,
ErrorCode,
HttpException,
} from '../../../../../../../../utils/errors'

const handler = async (req: NextApiRequest, res: NextApiResponse) => {
const commentId = decodeURIComponent(req.query.commentId.toString())
Expand Down
8 changes: 8 additions & 0 deletions packages/app/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ export interface DashboardPageProps {
}

const DashboardPage = ({ modelCategories }: DashboardPageProps) => {
if (!modelCategories) {
//? after upgrading to NextJS v15, hitting the back button to return to the homepage results in `undefined` props
//? this is a quick fix to reload the page if we encounter that scenario, as modelCategories should never be undefined
// TODO: figure out why NextJS v15 is not populating props correctly on back button click
window?.location.reload()
return null // return null to render nothing until the page refreshes
}

return (
<div>
<PageTitle title="" />
Expand Down
2 changes: 1 addition & 1 deletion packages/app/search/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export async function search(
}

//* This might be useful if directly integrated into the apiError function, but for now it's a one-off use case.
function formatAssertionError(error: Error | HttpException) {
function formatAssertionError(error: Error) {
return Error(`Lucene syntax error: ${error.message}.`, {
cause: { status: 400 },
})
Expand Down
4 changes: 2 additions & 2 deletions packages/app/setup/http.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import createError from 'http-errors'
import type { APIError, ErrorData } from '../declarations'

import type { UserDuringSetup } from './types'
Expand All @@ -14,8 +15,7 @@ async function fetchSeedDb(users: UserDuringSetup[]): Promise<ErrorData<null>> {

if (!response.ok) {
const { status, error }: APIError = await response.json()

throw new HttpException(ErrorCode.BadRequest, error) // TODO: figure out proper error code using the status
throw createError(status, error)
}

return [null, null]
Expand Down
6 changes: 2 additions & 4 deletions packages/app/setup/service.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import createError from 'http-errors'
import log from '../lib/log'
import { getModels } from '../models/service'
import { getSetupDb } from './db'
Expand All @@ -19,10 +20,7 @@ async function setUpNewInstallation(
}

if (!!models.length) {
throw new HttpException(
ErrorCode.BadRequest,
`mEditor's DB has already been seeded.`
)
throw new createError.BadRequest(`mEditor's DB has already been seeded.`)
}

await setupDb.seedDb(users)
Expand Down
7 changes: 3 additions & 4 deletions packages/app/workflows/service.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import createError from 'http-errors'
import log from '../lib/log'
import { getModel } from '../models/service'
import { getWorkflowsDb } from './db'
Expand Down Expand Up @@ -30,8 +31,7 @@ export async function getWorkflow(
const workflow = await workflowsDb.getWorkflow(workflowName)

if (!workflow) {
throw new HttpException(
ErrorCode.NotFound,
throw new createError.NotFound(
`The requested workflow, ${workflowName}, was not found.`
)
}
Expand Down Expand Up @@ -97,8 +97,7 @@ export function getWorkflowEdgeMatchingSourceAndTarget(

//! if we find more than one edge, the workflow is misconfigured, this is a FATAL error and we should immediately throw
if (matchingEdges.length > 1) {
throw new HttpException(
ErrorCode.InternalServerError,
throw new createError.InternalServerError(
`The workflow, ${workflow.name}, is misconfigured due to having duplicate edges for [source=${source}, target=${target}].`
)
}
Expand Down

0 comments on commit 5ecb56e

Please sign in to comment.