diff --git a/package-lock.json b/package-lock.json index 4df75f1..9323321 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@api-ts/openapi-generator": "^5.7.0", "@api-ts/response": "^2.1.0", "@api-ts/superagent-wrapper": "^1.3.3", - "@api-ts/typed-express-router": "^1.1.13", + "@api-ts/typed-express-router": "2.0.0", "@bitgo-beta/abstract-cosmos": "^1.0.1-beta.1049", "@bitgo-beta/abstract-eth": "1.0.2-beta.1298", "@bitgo-beta/abstract-utxo": "1.1.1-beta.1301", @@ -223,7 +223,9 @@ } }, "node_modules/@api-ts/typed-express-router": { - "version": "1.1.14", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@api-ts/typed-express-router/-/typed-express-router-2.0.0.tgz", + "integrity": "sha512-aCZYsgMdulvd78A3xFv7/D1FKLpuQLqdbC/qtKm0JP71Q2+rRaYm1AFA81wnbBUzlHXnwvbdqaIxWX8KX7n0HQ==", "license": "Apache-2.0", "dependencies": { "@api-ts/io-ts-http": "3.2.1", @@ -231,6 +233,14 @@ "express": "4.21.2", "fp-ts": "^2.0.0", "io-ts": "2.1.3" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + } } }, "node_modules/@api-ts/typed-express-router/node_modules/@types/express": { diff --git a/package.json b/package.json index 219656b..402d493 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "@api-ts/openapi-generator": "^5.7.0", "@api-ts/response": "^2.1.0", "@api-ts/superagent-wrapper": "^1.3.3", - "@api-ts/typed-express-router": "^1.1.13", + "@api-ts/typed-express-router": "2.0.0", "@bitgo-beta/abstract-cosmos": "^1.0.1-beta.1049", "@bitgo-beta/abstract-eth": "1.0.2-beta.1298", "@bitgo-beta/abstract-utxo": "1.1.1-beta.1301", diff --git a/src/advancedWalletManager/routers/advancedWalletManagerApiSpec.ts b/src/advancedWalletManager/routers/advancedWalletManagerApiSpec.ts index f14ecbf..adeffaf 100644 --- a/src/advancedWalletManager/routers/advancedWalletManagerApiSpec.ts +++ b/src/advancedWalletManager/routers/advancedWalletManagerApiSpec.ts @@ -35,6 +35,7 @@ import { ecdsaMPCv2Finalize } from '../handlers/ecdsaMPCV2WalletGenerationFinali import { ecdsaMPCv2Recovery } from '../handlers/ecdsaMPCV2Recovery'; import { signEddsaRecoveryTransaction } from '../handlers/eddsaMPCRecovery'; import { isEddsaCoin } from '../../shared/coinUtils'; +import { customDecodeErrorFormatter } from '../../shared/errorFormatters'; // Request type for /key/independent endpoint const IndependentKeyRequest = { @@ -489,7 +490,9 @@ export type GenericAwmApiSpecRouteRequest = AwmApiSpecRouteRequest; export function createKeyGenRouter( config: AdvancedWalletManagerConfig, ): WrappedRouter { - const router = createRouter(AdvancedWalletManagerApiSpec); + const router = createRouter(AdvancedWalletManagerApiSpec, { + decodeErrorFormatter: customDecodeErrorFormatter, + }); // Add middleware router.use(express.json()); router.use(prepareBitGo(config)); diff --git a/src/advancedWalletManager/routers/healthCheck.ts b/src/advancedWalletManager/routers/healthCheck.ts index f2a0edd..9c56bba 100644 --- a/src/advancedWalletManager/routers/healthCheck.ts +++ b/src/advancedWalletManager/routers/healthCheck.ts @@ -4,6 +4,7 @@ import { Response } from '@api-ts/response'; import pjson from '../../../package.json'; import { responseHandler } from '../../shared/middleware'; import { PingResponseType, VersionResponseType } from '../../types/health'; +import { customDecodeErrorFormatter } from '../../shared/errorFormatters'; // API Response types const PingResponse: HttpResponse = { @@ -38,7 +39,9 @@ export const HealthCheckApiSpec = apiSpec({ // Create router with handlers export function createHealthCheckRouter(): WrappedRouter { - const router = createRouter(HealthCheckApiSpec); + const router = createRouter(HealthCheckApiSpec, { + decodeErrorFormatter: customDecodeErrorFormatter, + }); // Ping endpoint handler router.post('v1.health.ping', [ responseHandler(() => diff --git a/src/masterBitgoExpress/routers/awmExpressHealth.ts b/src/masterBitgoExpress/routers/awmExpressHealth.ts index 58a8082..1edd58f 100644 --- a/src/masterBitgoExpress/routers/awmExpressHealth.ts +++ b/src/masterBitgoExpress/routers/awmExpressHealth.ts @@ -7,6 +7,7 @@ import logger from '../../shared/logger'; import { responseHandler } from '../../shared/middleware'; import { AdvancedWalletManagerClient } from '../clients/advancedWalletManagerClient'; import { PingResponseType, VersionResponseType } from '../../types/health'; +import { customDecodeErrorFormatter } from '../../shared/errorFormatters'; // Response type for /ping/advancedWalletManager endpoint const PingAwmResponse: HttpResponse = { @@ -54,7 +55,9 @@ export const AdvancedWalletManagerHealthSpec = apiSpec({ export function createAdvancedWalletManagerHealthRouter( cfg: MasterExpressConfig, ): WrappedRouter { - const router = createRouter(AdvancedWalletManagerHealthSpec); + const router = createRouter(AdvancedWalletManagerHealthSpec, { + decodeErrorFormatter: customDecodeErrorFormatter, + }); // Create an instance of awmClient const awmClient = new AdvancedWalletManagerClient(cfg); diff --git a/src/masterBitgoExpress/routers/healthCheck.ts b/src/masterBitgoExpress/routers/healthCheck.ts index 3ef2f8d..e146187 100644 --- a/src/masterBitgoExpress/routers/healthCheck.ts +++ b/src/masterBitgoExpress/routers/healthCheck.ts @@ -4,6 +4,7 @@ import { Response } from '@api-ts/response'; import pjson from '../../../package.json'; import { responseHandler } from '../../shared/middleware'; import { PingResponseType, VersionResponseType } from '../../types/health'; +import { customDecodeErrorFormatter } from '../../shared/errorFormatters'; // API Response types const PingResponse: HttpResponse = { @@ -40,7 +41,9 @@ export const HealthCheckApiSpec = apiSpec({ export function createHealthCheckRouter( serverType: string, ): WrappedRouter { - const router = createRouter(HealthCheckApiSpec); + const router = createRouter(HealthCheckApiSpec, { + decodeErrorFormatter: customDecodeErrorFormatter, + }); // Ping endpoint handler router.post('v1.health.ping', [ diff --git a/src/masterBitgoExpress/routers/masterBitGoExpressApiSpec.ts b/src/masterBitgoExpress/routers/masterBitGoExpressApiSpec.ts index c64e69a..0e29b1a 100644 --- a/src/masterBitgoExpress/routers/masterBitGoExpressApiSpec.ts +++ b/src/masterBitgoExpress/routers/masterBitGoExpressApiSpec.ts @@ -6,6 +6,7 @@ import { type WrappedRouter, } from '@api-ts/typed-express-router'; import express from 'express'; +import { customDecodeErrorFormatter } from '../../shared/errorFormatters'; import { MasterExpressConfig } from '../../shared/types'; import * as utxolib from '@bitgo-beta/utxo-lib'; import { prepareBitGo, responseHandler } from '../../shared/middleware'; @@ -82,7 +83,9 @@ export type GenericMasterApiSpecRouteRequest = MasterApiSpecRouteRequest { - const router = createRouter(MasterBitGoExpressApiSpec); + const router = createRouter(MasterBitGoExpressApiSpec, { + decodeErrorFormatter: customDecodeErrorFormatter, + }); // Add middleware to all routes router.use(parseBody); diff --git a/src/shared/errorFormatters.ts b/src/shared/errorFormatters.ts new file mode 100644 index 0000000..290cf27 --- /dev/null +++ b/src/shared/errorFormatters.ts @@ -0,0 +1,8 @@ +import * as PathReporter from 'io-ts/lib/PathReporter'; +import { DecodeErrorFormatterFn } from '@api-ts/typed-express-router'; + +export const customDecodeErrorFormatter: DecodeErrorFormatterFn = (errs, _req) => { + const validationErrors = PathReporter.failure(errs); + const validationErrorMessage = validationErrors.join('\n'); + return { error: validationErrorMessage }; +};