Compare commits

...

7 Commits

Author SHA1 Message Date
vchikalkin
1d9c35b953 pages/api/trpc: track only server errors 2023-10-04 17:33:57 +03:00
vchikalkin
4dd4038091 utils/trpc: map http to trpc errors 2023-10-04 17:33:05 +03:00
vchikalkin
3aea4c439f trpc: validation errors now throw 400 error 2023-10-04 17:09:00 +03:00
vchikalkin
240b92f84d pass error code to trpc response 2023-10-04 16:42:47 +03:00
vchikalkin
0170d64700 utils/axios: capture only >500 errors
process/load-kp: remove error capture
2023-10-03 15:10:46 +03:00
vchikalkin
2a8e3fb443 elt/osago: get error message 2023-10-03 14:48:41 +03:00
vchikalkin
af34a55c17 upgrade for new elt backend 2023-10-03 14:35:17 +03:00
16 changed files with 355 additions and 339 deletions

View File

@ -57,7 +57,6 @@ export const Kasko = observer(() => {
)
.then((res) => {
if (res) {
const companyRes = res?.[row.id];
const {
kaskoSum = 0,
message,
@ -65,8 +64,8 @@ export const Kasko = observer(() => {
totalFranchise = 0,
requestId,
paymentPeriods,
} = companyRes;
let { error } = companyRes;
} = res;
let { error } = res;
if (totalFranchise > MAX_FRANCHISE) {
error ||= `Франшиза по страховке превышает максимально допустимое значение: ${Intl.NumberFormat(
@ -111,10 +110,11 @@ export const Kasko = observer(() => {
}
})
.catch((error) => {
const _err = error as Error;
$tables.elt.kasko.setRow({
...initialData,
key,
message: error,
message: _err.message || String(error),
status: 'error',
});
});

View File

@ -51,9 +51,8 @@ export const Osago = observer(() => {
)
.then((res) => {
if (res) {
const companyRes = res?.[row.id];
const { numCalc, premiumSum = 0, message, skCalcId } = companyRes;
let { error } = companyRes;
const { numCalc, premiumSum = 0, message, skCalcId } = res;
let { error } = res;
if (premiumSum > MAX_INSURANCE) {
error ||= `Сумма по страховке превышает максимально допустимое значение по стоимости ОСАГО: ${Intl.NumberFormat(
'ru',
@ -83,10 +82,11 @@ export const Osago = observer(() => {
}
})
.catch((error) => {
const _err = error as Error;
$tables.elt.osago.setRow({
...initialData,
key,
message: error,
message: _err.message || String(error),
status: 'error',
});
});

View File

@ -231,7 +231,8 @@ export async function makeEltOsagoRequest(
}
return {
ELTParams: {
companyId: row.id,
params: {
FullDriversInfo: [
{
kbm: '3',
@ -272,7 +273,6 @@ export async function makeEltOsagoRequest(
ownerType: 1,
tsToRegistrationPlace: 0,
},
companyIds: [row.id],
preparams: {
brandId,
kladr,
@ -611,7 +611,8 @@ export async function makeEltKaskoRequest(
}
return {
ELTParams: {
companyId: row.id,
params: {
Insurer: {
SubjectType: 1,
SubjectTypeSpecified: true,
@ -697,7 +698,6 @@ export async function makeEltKaskoRequest(
// },
// ],
},
companyIds: [row.id],
preparams: {
brandId,
kladr,

View File

@ -1,7 +1,8 @@
import { z } from 'zod';
export const RequestEltKaskoSchema = z.object({
ELTParams: z.object({
companyId: z.string(),
params: z.object({
Insurer: z.object({
SubjectType: z.number(),
SubjectTypeSpecified: z.boolean(),
@ -82,7 +83,6 @@ export const RequestEltKaskoSchema = z.object({
vehicleDateSpecified: z.boolean(),
vehicleYear: z.number(),
}),
companyIds: z.array(z.string()),
preparams: z.object({
brandId: z.string(),
kladr: z.string(),
@ -98,85 +98,84 @@ export const RequestEltKaskoSchema = z.object({
}),
});
export const ResultEltKaskoSchema = z.record(
z.object({
calcInfo: z.null(),
comment: z.null(),
doSum: z.number(),
error: z.string(),
errorType: z.null(),
gapSum: z.number(),
goSum: z.number(),
insuranceCompanyFranchise: z.object({ id: z.string(), value: z.string() }),
insuranceCompanyGo: z.object({ id: z.string(), value: z.string() }),
isNeedInspection: z.string(),
kaskoSum: z.number(),
kbmOsago: z.null(),
message: z.string(),
nsSum: z.number(),
options: z.array(
z.union([
z.object({
id: z.string(),
name: z.string(),
values: z.array(z.object({ id: z.string(), name: z.string() })),
}),
z.object({
id: z.string(),
name: z.string(),
values: z.array(z.object({ id: z.string(), name: z.null() })),
}),
z.object({
id: z.string(),
name: z.string(),
values: z.array(z.object({ id: z.null(), name: z.null() })),
}),
])
),
paymentPeriods: z.array(
export const ResultEltKaskoSchema = z.object({
calcInfo: z.null(),
comment: z.null(),
doSum: z.number(),
error: z.string(),
errorType: z.null(),
gapSum: z.number(),
goSum: z.number(),
insuranceCompanyFranchise: z.object({ id: z.string(), value: z.string() }),
insuranceCompanyGo: z.object({ id: z.string(), value: z.string() }),
isNeedInspection: z.string(),
kaskoSum: z.number(),
kbmOsago: z.null(),
message: z.string(),
nsSum: z.number(),
options: z.array(
z.union([
z.object({
date: z.string(),
doSum: z.number(),
doSumSpecified: z.boolean(),
duration: z.number(),
durationSpecified: z.boolean(),
franchiseSum: z.number(),
franchiseSumSpecified: z.boolean(),
gapSum: z.number(),
gapSumSpecified: z.boolean(),
goSum: z.number(),
goSumSpecified: z.boolean(),
id: z.null(),
kaskoSum: z.number(),
kaskoSumSpecified: z.boolean(),
name: z.null(),
nsSum: z.number(),
nsSumSpecified: z.boolean(),
num: z.number(),
numSpecified: z.boolean(),
premiumSum: z.number(),
premiumSumSpecified: z.boolean(),
rate: z.number(),
rateSpecified: z.boolean(),
})
),
policyNumber: z.null(),
premiumSum: z.number(),
product: z.string(),
productId: z.string(),
program: z.string(),
programCode: z.string(),
programId: z.string(),
requestId: z.string(),
skCalcId: z.string(),
totalFranchise: z.number(),
totalFranchiseSpecified: z.boolean(),
unicusGUID: z.string(),
})
);
id: z.string(),
name: z.string(),
values: z.array(z.object({ id: z.string(), name: z.string() })),
}),
z.object({
id: z.string(),
name: z.string(),
values: z.array(z.object({ id: z.string(), name: z.null() })),
}),
z.object({
id: z.string(),
name: z.string(),
values: z.array(z.object({ id: z.null(), name: z.null() })),
}),
])
),
paymentPeriods: z.array(
z.object({
date: z.string(),
doSum: z.number(),
doSumSpecified: z.boolean(),
duration: z.number(),
durationSpecified: z.boolean(),
franchiseSum: z.number(),
franchiseSumSpecified: z.boolean(),
gapSum: z.number(),
gapSumSpecified: z.boolean(),
goSum: z.number(),
goSumSpecified: z.boolean(),
id: z.null(),
kaskoSum: z.number(),
kaskoSumSpecified: z.boolean(),
name: z.null(),
nsSum: z.number(),
nsSumSpecified: z.boolean(),
num: z.number(),
numSpecified: z.boolean(),
premiumSum: z.number(),
premiumSumSpecified: z.boolean(),
rate: z.number(),
rateSpecified: z.boolean(),
})
),
policyNumber: z.null(),
premiumSum: z.number(),
product: z.string(),
productId: z.string(),
program: z.string(),
programCode: z.string(),
programId: z.string(),
requestId: z.string(),
skCalcId: z.string(),
totalFranchise: z.number(),
totalFranchiseSpecified: z.boolean(),
unicusGUID: z.string(),
});
export const RequestEltOsagoSchema = z.object({
ELTParams: z.object({
companyId: z.string(),
params: z.object({
FullDriversInfo: z.array(z.object({ kbm: z.string() })),
carInfo: z.object({
mark: z.string(),
@ -244,7 +243,6 @@ export const RequestEltOsagoSchema = z.object({
ownerType: z.number(),
tsToRegistrationPlace: z.number(),
}),
companyIds: z.array(z.string()),
preparams: z.object({
brandId: z.string(),
kladr: z.string(),
@ -252,27 +250,25 @@ export const RequestEltOsagoSchema = z.object({
}),
});
export const ResultEltOsagoSchema = z.record(
z.object({
calcInfo: z.array(
z.object({
itemName: z.string(),
value: z.number(),
valueSpecified: z.boolean(),
})
),
error: z.string(),
fullDriversInfo: z.array(z.unknown()),
kbm: z.object({ class: z.number(), value: z.number() }),
message: z.string(),
numCalc: z.number(),
premiumSum: z.number(),
prevoiusKBM: z.object({ class: z.number(), value: z.number() }),
rsaRequestId: z.string(),
skCalcId: z.string(),
tb: z.number(),
})
);
export const ResultEltOsagoSchema = z.object({
calcInfo: z.array(
z.object({
itemName: z.string(),
value: z.number(),
valueSpecified: z.boolean(),
})
),
error: z.string(),
fullDriversInfo: z.array(z.unknown()),
kbm: z.object({ class: z.number(), value: z.number() }),
message: z.string(),
numCalc: z.number(),
premiumSum: z.number(),
prevoiusKBM: z.object({ class: z.number(), value: z.number() }),
rsaRequestId: z.string(),
skCalcId: z.string(),
tb: z.number(),
});
export const RowSchema = z.object({
id: z.string(),

View File

@ -28,53 +28,46 @@ const { URL_GET_USER, URL_CORE_FINGAP, URL_1C_TRANSTAX, URL_ELT_OSAGO, URL_ELT_K
export const handlers = [
rest.get(URL_GET_USER, (req, res, ctx) => res(ctx.json(users.akalinina))),
rest.post(URL_CORE_FINGAP, (req, res, ctx) => res(
rest.post(URL_CORE_FINGAP, (req, res, ctx) =>
res(
ctx.json({
sum: _.random(100000, 200000),
premium: _.random(1000, 10000),
})
)),
rest.post(URL_1C_TRANSTAX, (req, res, ctx) => res(
)
),
rest.post(URL_1C_TRANSTAX, (req, res, ctx) =>
res(
ctx.json({
error: null,
tax: _.random(100000, 200000),
})
)
),
rest.post(URL_ELT_OSAGO, async (req, res, ctx) => res(
ctx.json({
numCalc: _.random(1000000, 3000000),
skCalcId: _.random(50000000, 60000000).toString(),
premiumSum: _.random(10000, 20000),
message: 'OSAGO Message',
})
)),
rest.post(URL_ELT_OSAGO, async (req, res, ctx) => {
const companyId = (await req.json()).companyIds[0];
return res(
rest.post(URL_ELT_KASKO, async (req, res, ctx) => res(
ctx.json({
[companyId]: {
numCalc: _.random(1000000, 3000000),
skCalcId: _.random(50000000, 60000000).toString(),
premiumSum: _.random(10000, 20000),
message: 'OSAGO Message',
},
requestId: _.random(3000000, 4000000).toString(),
skCalcId: _.random(50000000, 60000000).toString(),
message: 'KASKO Message',
premiumSum: _.random(100000, 200000),
kaskoSum: _.random(100000, 200000),
paymentPeriods: [
{
num: 1,
kaskoSum: _.random(100000, 200000),
},
],
totalFranchise: _.random(20000, 40000),
})
);
}),
rest.post(URL_ELT_KASKO, async (req, res, ctx) => {
const companyId = (await req.json()).companyIds[0];
return res(
ctx.json({
[companyId]: {
requestId: _.random(3000000, 4000000).toString(),
skCalcId: _.random(50000000, 60000000).toString(),
message: 'KASKO Message',
premiumSum: _.random(100000, 200000),
kaskoSum: _.random(100000, 200000),
paymentPeriods: [
{
num: 1,
kaskoSum: _.random(100000, 200000),
},
],
totalFranchise: _.random(20000, 40000),
},
})
);
}),
)),
// rest.post(URL_CRM_GRAPHQL, (req, res, ctx) => {
// return res(ctx.status(503));

View File

@ -23,16 +23,17 @@ export default trpcNext.createNextApiHandler({
onError(opts) {
const { error } = opts;
// send to bug reporting
withScope((scope) => {
(Object.keys(opts) as Array<keyof typeof opts>).forEach((key) => {
if (key !== 'req') {
let extra = opts[key];
if (key === 'input') extra = JSON.stringify(extra);
scope.setExtra(key, extra);
}
if (!['BAD_REQUEST', 'UNAUTHORIZED', 'FORBIDDEN'].includes(error.code))
withScope((scope) => {
(Object.keys(opts) as Array<keyof typeof opts>).forEach((key) => {
if (key !== 'req') {
let extra = opts[key];
if (key === 'input') extra = JSON.stringify(extra);
scope.setExtra(key, extra);
}
});
captureException(error);
});
captureException(error);
});
// eslint-disable-next-line no-console
console.error('Something went wrong', error);
},

View File

@ -34,24 +34,15 @@ export async function action({ store, trpcClient }: ProcessContext) {
values,
})
.then((res) => {
if (res.success === false) {
notification.error({
description: res.error,
key,
message: errorMessage,
placement: 'bottomRight',
});
} else {
$results.setPayments(res.data.resultPayments);
$results.setValues(res.data.resultValues);
$calculation.$values.setValues(res.data.values);
$results.setPayments(res.data.resultPayments);
$results.setValues(res.data.resultValues);
$calculation.$values.setValues(res.data.values);
notification.success({
key,
message: successMessage,
placement: 'bottomRight',
});
}
notification.success({
key,
message: successMessage,
placement: 'bottomRight',
});
})
.catch((error_) => {
const error = error_ as Error;

View File

@ -42,42 +42,33 @@ export function action({ store, trpcClient, apolloClient }: ProcessContext) {
values,
})
.then(async (res) => {
if (res.success === false) {
notification.error({
description: res.error,
key,
message: errorMessage,
placement: 'bottomRight',
});
} else {
$results.setPayments(res.data.resultPayments);
$results.setValues(res.data.resultValues);
$calculation.$values.setValues({ ...res.data.values, recalcWithRevision: false });
$results.setPayments(res.data.resultPayments);
$results.setValues(res.data.resultValues);
$calculation.$values.setValues({ ...res.data.values, recalcWithRevision: false });
notification.success({
key,
message: successMessage,
placement: 'bottomRight',
notification.success({
key,
message: successMessage,
placement: 'bottomRight',
});
const leadid = $calculation.element('selectLead').getValue();
if (leadid) {
const {
data: { quotes },
} = await apolloClient.query({
fetchPolicy: 'network-only',
query: CRMTypes.GetQuotesDocument,
variables: {
leadid,
},
});
const leadid = $calculation.element('selectLead').getValue();
if (leadid) {
const {
data: { quotes },
} = await apolloClient.query({
fetchPolicy: 'network-only',
query: CRMTypes.GetQuotesDocument,
variables: {
leadid,
},
});
$calculation
.element('selectQuote')
.setOptions(normalizeOptions(quotes))
.setValue(values.quote);
}
$calculation
.element('selectQuote')
.setOptions(normalizeOptions(quotes))
.setValue(values.quote);
}
})
.catch((error_) => {

View File

@ -2,13 +2,12 @@
import eltHelper from '../elt/lib/helper';
import { message } from '@/Components/Common/Notification';
import type { ProcessContext } from '@/process/types';
import { captureException, withScope } from '@sentry/nextjs';
import { reaction } from 'mobx';
import { omit } from 'radash';
const key = 'KP_LOADING_INFO';
export function common({ store, trpcClient, apolloClient, user }: ProcessContext) {
export function common({ store, trpcClient, apolloClient }: ProcessContext) {
const { $calculation, $process, $tables } = store;
const { init: initElt } = eltHelper({ apolloClient, store });
@ -86,18 +85,12 @@ export function common({ store, trpcClient, apolloClient, user }: ProcessContext
key,
});
})
.catch((error_) => {
.catch(() => {
message.error({
content: `Ошибка во время загрузки КП ${quote.label}`,
key,
});
$calculation.element('selectQuote').resetValue();
withScope((scope) => {
scope.setExtra('quote', quote);
scope.setExtra('user', user);
captureException(error_);
});
})
.finally(() => {
$process.delete('LoadKP');

View File

@ -7,6 +7,8 @@ import { calculate } from '@/api/core/query';
import type { User } from '@/api/user/types';
import initializeApollo from '@/apollo/client';
import { protectedProcedure } from '@/server/procedure';
import { HttpError } from '@/utils/error';
import { createTRPCError } from '@/utils/trpc';
import { QueryClient } from '@tanstack/react-query';
export const calculateRouter = router({
@ -17,55 +19,56 @@ export const calculateRouter = router({
const apolloClient = initializeApollo();
const queryClient = new QueryClient();
if (!ctx.unlimited) {
const validationResult = await validate({
try {
if (!ctx.unlimited) {
const validationResult = await validate({
context: {
apolloClient,
queryClient,
user: ctx.user,
},
input,
});
if (validationResult.success === false) {
throw new HttpError(validationResult.message, 400);
}
}
let user: Pick<User, 'domainName'> = { domainName: ctx.user.domainName };
if (ctx.unlimited && input.values.user) {
user = { domainName: input.values.user };
}
const requestData = await createRequestData({
context: {
apolloClient,
queryClient,
user: ctx.user,
...ctx,
user,
},
input,
});
if (validationResult.success === false) {
return {
error: validationResult.error,
success: false,
};
const calculateResult = await calculate(requestData);
const result = transformCalculateResults({
calculateInput: input,
requestCalculate: requestData,
responseCalculate: calculateResult,
});
// TEMP
if (ctx.unlimited) {
result.__calculateResult = calculateResult;
}
return {
data: result,
success: true,
};
} catch (error) {
throw createTRPCError(error);
}
let user: Pick<User, 'domainName'> = { domainName: ctx.user.domainName };
if (ctx.unlimited && input.values.user) {
user = { domainName: input.values.user };
}
const requestData = await createRequestData({
context: {
apolloClient,
queryClient,
...ctx,
user,
},
input,
});
const calculateResult = await calculate(requestData);
const result = transformCalculateResults({
calculateInput: input,
requestCalculate: requestData,
responseCalculate: calculateResult,
});
// TEMP
if (ctx.unlimited) {
result.__calculateResult = calculateResult;
}
return {
data: result,
success: true,
};
}),
});

View File

@ -49,14 +49,14 @@ export async function validate({ input, context }: { context: Context; input: Ca
});
if (validationResult.success === false) {
const error = getMessage(validationResult.error.errors);
const message = getMessage(validationResult.error.errors);
return { error, success: false };
return { message, success: false };
}
}
return {
error: '',
message: '',
success: true,
};
}

View File

@ -34,15 +34,9 @@ export const OutputDataSchema = z.object({
export type OutputData = z.infer<typeof OutputDataSchema>;
export const CalculateOutputSchema = z.union([
z.object({
data: OutputDataSchema,
success: z.literal(true),
}),
z.object({
error: z.string(),
success: z.literal(false),
}),
]);
export const CalculateOutputSchema = z.object({
data: OutputDataSchema,
success: z.literal(true),
});
export type CalculateOutput = z.infer<typeof CalculateOutputSchema>;

View File

@ -34,6 +34,8 @@ import * as price from '@/process/price';
import * as subsidy from '@/process/subsidy';
import * as supplierAgent from '@/process/supplier-agent';
import type { CalculationValues } from '@/stores/calculation/values/types';
import { HttpError } from '@/utils/error';
import { createTRPCError } from '@/utils/trpc';
import { QueryClient } from '@tanstack/react-query';
const { DEFAULT_FINGAP_ROW, DEFAULT_KASKO_ROW, DEFAULT_OSAGO_ROW } = insuranceTable;
@ -96,70 +98,71 @@ export const quoteRouter = router({
const apolloClient = initializeApollo();
const queryClient = new QueryClient();
if (!ctx.unlimited) {
const validationResult = await validate({
try {
if (!ctx.unlimited) {
const validationResult = await validate({
context: {
apolloClient,
queryClient,
user: ctx.user,
},
input,
});
if (validationResult.success === false) {
throw new HttpError(validationResult.message, 400);
}
}
let user: Pick<User, 'domainName'> = { domainName: ctx.user.domainName };
if (ctx.unlimited && input.values.user) {
user = { domainName: input.values.user };
}
const requestData = await createRequestData({
context: {
apolloClient,
queryClient,
user: ctx.user,
...ctx,
user,
},
input,
});
if (validationResult.success === false) {
return {
error: validationResult.error,
success: false,
};
const calculateResult = await calculate(requestData);
const requestCreateKP = compatRequestCreateKP({
domainName: user.domainName,
finGAP: input.fingap,
insurance: Object.values(input.insurance.values),
calculation: {
calculationValues: await compatValues(input.values, { apolloClient }),
...calculateResult,
preparedPayments: requestData.preparedPayments,
additionalData: requestData.additionalData,
},
elt: input.elt,
});
const createKPResult = await createKP(requestCreateKP);
const result = transformCalculateResults({
calculateInput: input,
requestCalculate: requestData,
responseCalculate: calculateResult,
});
if (URL_CRM_DOWNLOADKP) {
result.values.downloadKp = URL_CRM_DOWNLOADKP?.concat(createKPResult.offerprintformapi);
}
return {
data: result,
success: true,
};
} catch (error) {
throw createTRPCError(error);
}
let user: Pick<User, 'domainName'> = { domainName: ctx.user.domainName };
if (ctx.unlimited && input.values.user) {
user = { domainName: input.values.user };
}
const requestData = await createRequestData({
context: {
apolloClient,
queryClient,
...ctx,
user,
},
input,
});
const calculateResult = await calculate(requestData);
const requestCreateKP = compatRequestCreateKP({
domainName: user.domainName,
finGAP: input.fingap,
insurance: Object.values(input.insurance.values),
calculation: {
calculationValues: await compatValues(input.values, { apolloClient }),
...calculateResult,
preparedPayments: requestData.preparedPayments,
additionalData: requestData.additionalData,
},
elt: input.elt,
});
const createKPResult = await createKP(requestCreateKP);
const result = transformCalculateResults({
calculateInput: input,
requestCalculate: requestData,
responseCalculate: calculateResult,
});
if (URL_CRM_DOWNLOADKP) {
result.values.downloadKp = URL_CRM_DOWNLOADKP?.concat(createKPResult.offerprintformapi);
}
return {
data: result,
success: true,
};
}),
});

View File

@ -1,3 +1,4 @@
import { HttpError } from './error';
import { captureException, withScope } from '@sentry/nextjs';
import type { AxiosError } from 'axios';
import { isAxiosError } from 'axios';
@ -17,25 +18,28 @@ function getErrorMessage<T extends { error?: string; errors?: string[]; message?
export async function withHandleError<T>(fn: Promise<T>) {
return fn.catch((error_: AxiosError | Error) => {
if (isAxiosError(error_)) {
const err = pick(error_, ['code', 'message', 'status', 'cause']);
const data = error_.config?.data;
const params = error_.config?.params;
const message = getErrorMessage(error_);
const opts = { ...err, data, message, params };
error_.message += ` | ${message}`;
if (error_.response?.status && error_.response?.status >= 500) {
const err = pick(error_, ['code', 'message', 'status', 'cause']);
const data = error_.config?.data;
const params = error_.config?.params;
withScope((scope) => {
(Object.keys(opts) as Array<keyof typeof opts>).forEach((key) => {
let extra = opts[key];
if (key === 'data') extra = JSON.stringify(extra);
scope.setExtra(key, extra);
const opts = { ...err, data, message, params };
error_.message += ` | ${message}`;
withScope((scope) => {
(Object.keys(opts) as Array<keyof typeof opts>).forEach((key) => {
let extra = opts[key];
if (key === 'data') extra = JSON.stringify(extra);
scope.setExtra(key, extra);
});
captureException(error_);
});
captureException(error_);
});
}
throw new Error(message);
throw new HttpError(message, error_.status || error_.response?.status);
}
return null as unknown as T;

9
apps/web/utils/error.ts Normal file
View File

@ -0,0 +1,9 @@
export class HttpError extends Error {
public statusCode: number;
constructor(message: string, statusCode = 500) {
super(message);
this.name = 'HttpError';
this.statusCode = statusCode;
}
}

38
apps/web/utils/trpc.ts Normal file
View File

@ -0,0 +1,38 @@
import { HttpError } from './error';
import { TRPCError } from '@trpc/server';
import type { TRPC_ERROR_CODE_KEY } from '@trpc/server/rpc';
const HTTP_CODE_TO_JSONRPC2: Record<number, TRPC_ERROR_CODE_KEY> = {
400: 'BAD_REQUEST',
401: 'UNAUTHORIZED',
403: 'FORBIDDEN',
404: 'NOT_FOUND',
405: 'METHOD_NOT_SUPPORTED',
408: 'TIMEOUT',
409: 'CONFLICT',
412: 'PRECONDITION_FAILED',
413: 'PAYLOAD_TOO_LARGE',
429: 'TOO_MANY_REQUESTS',
499: 'CLIENT_CLOSED_REQUEST',
500: 'INTERNAL_SERVER_ERROR',
};
export function createTRPCError(error: unknown) {
let code: TRPC_ERROR_CODE_KEY = 'INTERNAL_SERVER_ERROR';
let message = '';
if (error instanceof HttpError) {
const { statusCode = 500 } = error;
code = HTTP_CODE_TO_JSONRPC2[statusCode];
}
if (error instanceof Error) {
message = error.message;
}
return new TRPCError({
cause: error,
code,
message,
});
}