Files
speckle-server/packages/server/modules/shared/errors/base.ts
T
Kristaps Fabians Geikins bde148f286 chore(server): migrating fully to ESM (#5042)
* wip

* some extra fixes

* stuff kinda works?

* need to figure out mocks

* need to figure out mocks

* fix db listener

* gqlgen fix

* minor gqlgen watch adjustment

* lint fixes

* delete old codegen file

* converting migrations to ESM

* getModuleDIrectory

* vitest sort of works

* added back ts-vitest

* resolve gql double load

* fixing test timeout configs

* TSC lint fix

* fix automate tests

* moar debugging

* debugging

* more debugging

* codegen update

* server works

* yargs migrated

* chore(server): getting rid of global mocks for Server ESM (#5046)

* got rid of email mock

* got rid of comment mocks

* got rid of multi region mocks

* got rid of stripe mock

* admin override mock updated

* removed final mock

* fixing import.meta.resolve calls

* another import.meta.resolve fix

* added requested test

* nyc ESM fix

* removed unneeded deps + linting

* yarn lock forgot to commit

* tryna fix flakyness

* email capture util fix

* sendEmail fix

* fix TSX check

* sender transporter fix + CR comments

* merge main fix

* test fixx

* circleci fix

* gqlgen bigint fix

* error formatter fix

* more error formatting improvements

* esmloader added to Dockerfile

* more dockerfile fixes

* bg jobs fix
2025-07-14 10:26:19 +03:00

87 lines
2.5 KiB
TypeScript

import { Merge } from 'type-fest'
import type { Options, Info } from 'verror'
import VError from 'verror'
export type ExtendedOptions<I extends Info = Info> = Merge<
Options,
{ info?: Partial<I> }
> & {
statusCode?: number
}
/**
* Base application error (don't use directly, treat it as abstract). Built on top of `verror` so that you can
* chain errors (e.cause is the previous error) and also add arbitrary metadata using the `info` option.
*
* This allows for much nicer error handling & monitoring
*/
export class BaseError<I extends Info = Info> extends VError {
/**
* Error code (override in child class)
*/
static code = 'BASE_APP_ERROR'
/**
* Default message if none is passed
*/
static defaultMessage = 'Unexpected error occurred!'
/**
* Status code to use if error is thrown in a REST API
*/
static statusCode = 500
/**
*
* @param message A string, which can use templates.
* Templates require the property to be within curly brackets, e.g. `{property}`.
* Templates can include simple if conditionals, e.g. `{if property}some string{end}`.
* Properties should be passed to the options.info property.
* Properties within options.info can be nested, e.g. `{property.subProperty}`.
* @param options If an Error is passed, it will be used as the cause.
* If an object is passed, it will be used as the options.
* If message template format is used in the message,
* the info property of the options must contain the properties to use. e.g. `{info: {property: 'value'}}`.
*/
constructor(
message?: string | null,
options: ExtendedOptions<I> | Error | undefined = undefined
) {
// Resolve options correctly
if (options) {
const cause = options instanceof Error ? options : options.cause
options = options instanceof Error ? { cause } : options
} else {
options = {}
}
const info = {
...(options.info || {}),
code: new.target.code,
statusCode: options?.statusCode || new.target.statusCode
}
options.info = info as unknown as I
// Get message from defaultMessage, if it's empty
if (!message) {
message = new.target.defaultMessage
}
// Resolve constructor name
const constructorName = new.target.name
options.name = constructorName
super(options, message)
}
/**
* Get collected info of this object and previous errors
*/
info() {
return BaseError.info(this) as Partial<I>
}
}
export type { Info }