diff --git a/package-lock.json b/package-lock.json index 2a8c67d..60642e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.11.0", "license": "MIT", "dependencies": { + "@bangbang93/service-errors": "^1.1.1", "@bangbang93/utils": "^6.9.1", "@mongodb-js/zstd": "^1.2.0", "@xmcl/nat-api": "^0.4.3", @@ -99,6 +100,16 @@ "typescript": "^5" } }, + "node_modules/@bangbang93/service-errors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@bangbang93/service-errors/-/service-errors-1.1.1.tgz", + "integrity": "sha512-EB7UTxE1aFzyMAJ+TKNtJIw3zNee2Sww/quIZ6w0B53z3PLpdLqLPPU0zqq/a+cLG5rLvHFu00EL20oZnUgffQ==", + "license": "ISC", + "dependencies": { + "lodash": "^4.17.21", + "pony-cause": "^2.1.10" + } + }, "node_modules/@bangbang93/utils": { "version": "6.9.1", "resolved": "https://registry.npmjs.org/@bangbang93/utils/-/utils-6.9.1.tgz", @@ -4678,6 +4689,15 @@ "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" }, + "node_modules/pony-cause": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/pony-cause/-/pony-cause-2.1.11.tgz", + "integrity": "sha512-M7LhCsdNbNgiLYiP4WjsfLUuFmCfnjdF6jKe2R9NKl4WFN+HZPGHJZ9lnLP7f9ZnKe3U9nuWD0szirmj+migUg==", + "license": "0BSD", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -5994,6 +6014,15 @@ "yaml": "^2.3.1" } }, + "@bangbang93/service-errors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@bangbang93/service-errors/-/service-errors-1.1.1.tgz", + "integrity": "sha512-EB7UTxE1aFzyMAJ+TKNtJIw3zNee2Sww/quIZ6w0B53z3PLpdLqLPPU0zqq/a+cLG5rLvHFu00EL20oZnUgffQ==", + "requires": { + "lodash": "^4.17.21", + "pony-cause": "^2.1.10" + } + }, "@bangbang93/utils": { "version": "6.9.1", "resolved": "https://registry.npmjs.org/@bangbang93/utils/-/utils-6.9.1.tgz", @@ -9162,6 +9191,11 @@ "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz", "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" }, + "pony-cause": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/pony-cause/-/pony-cause-2.1.11.tgz", + "integrity": "sha512-M7LhCsdNbNgiLYiP4WjsfLUuFmCfnjdF6jKe2R9NKl4WFN+HZPGHJZ9lnLP7f9ZnKe3U9nuWD0szirmj+migUg==" + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", diff --git a/package.json b/package.json index 332ce6d..e2baa91 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ }, "homepage": "https://github.com/bangbang93/openbmclapi#readme", "dependencies": { + "@bangbang93/service-errors": "^1.1.1", "@bangbang93/utils": "^6.9.1", "@mongodb-js/zstd": "^1.2.0", "@xmcl/nat-api": "^0.4.3", diff --git a/src/cluster.ts b/src/cluster.ts index 583268c..34445f1 100644 --- a/src/cluster.ts +++ b/src/cluster.ts @@ -30,6 +30,7 @@ import {FileListSchema} from './constants.js' import {validateFile} from './file.js' import {Keepalive} from './keepalive.js' import {logger} from './logger.js' +import {beforeError} from './modules/got-hooks.js' import {AuthRouteFactory} from './routes/auth.route.js' import MeasureRouteFactory from './routes/measure.route.js' import {getStorage, type IStorage} from './storage/base.storage.js' @@ -117,6 +118,7 @@ export class Cluster { } }, ], + beforeError, }, }) this.storage = getStorage(config) diff --git a/src/modules/got-hooks.ts b/src/modules/got-hooks.ts new file mode 100644 index 0000000..a6395b3 --- /dev/null +++ b/src/modules/got-hooks.ts @@ -0,0 +1,16 @@ +import {ServiceError} from '@bangbang93/service-errors' +import {BeforeErrorHook, HTTPError, RequestError} from 'got' + +export const beforeError: BeforeErrorHook[] = [catchServiceError] + +export function catchServiceError(error: RequestError): RequestError { + if (error instanceof HTTPError) { + if (error.response.headers['content-type']?.includes('application/json')) { + const body = JSON.parse(error.response.body.toString()) + if (ServiceError.isServiceError(body)) { + throw ServiceError.fromJSON(body as unknown as Record) + } + } + } + return error +} diff --git a/src/token.ts b/src/token.ts index 59d8c88..468ca93 100644 --- a/src/token.ts +++ b/src/token.ts @@ -2,6 +2,7 @@ import got, {type Got} from 'got' import ms from 'ms' import {createHmac} from 'node:crypto' import {logger} from './logger.js' +import {beforeError} from './modules/got-hooks.js' export class TokenManager { private token: string | undefined @@ -22,6 +23,9 @@ export class TokenManager { timeout: { request: ms('5m'), }, + hooks: { + beforeError, + }, }) }