mirror of
https://github.com/documenso/documenso.git
synced 2025-11-10 04:22:32 +10:00
Compare commits
2 Commits
v1.12.0-rc
...
feat/error
| Author | SHA1 | Date | |
|---|---|---|---|
| 824f4a070a | |||
| 2c8d11c37d |
@ -1,4 +1,5 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
|
const { withAxiom } = require('next-axiom');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { version } = require('./package.json');
|
const { version } = require('./package.json');
|
||||||
@ -91,4 +92,4 @@ const config = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = config;
|
module.exports = withAxiom(config);
|
||||||
|
|||||||
@ -33,6 +33,7 @@
|
|||||||
"micro": "^10.0.1",
|
"micro": "^10.0.1",
|
||||||
"next": "14.0.3",
|
"next": "14.0.3",
|
||||||
"next-auth": "4.24.5",
|
"next-auth": "4.24.5",
|
||||||
|
"next-axiom": "^1.1.1",
|
||||||
"next-plausible": "^3.10.1",
|
"next-plausible": "^3.10.1",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"perfect-freehand": "^1.2.0",
|
"perfect-freehand": "^1.2.0",
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { Suspense } from 'react';
|
|||||||
|
|
||||||
import { Caveat, Inter } from 'next/font/google';
|
import { Caveat, Inter } from 'next/font/google';
|
||||||
|
|
||||||
|
import { AxiomWebVitals } from 'next-axiom';
|
||||||
import { PublicEnvScript } from 'next-runtime-env';
|
import { PublicEnvScript } from 'next-runtime-env';
|
||||||
|
|
||||||
import { FeatureFlagProvider } from '@documenso/lib/client-only/providers/feature-flag';
|
import { FeatureFlagProvider } from '@documenso/lib/client-only/providers/feature-flag';
|
||||||
@ -71,6 +72,8 @@ export default async function RootLayout({ children }: { children: React.ReactNo
|
|||||||
<PublicEnvScript />
|
<PublicEnvScript />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
<AxiomWebVitals />
|
||||||
|
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<PostHogPageview />
|
<PostHogPageview />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|||||||
22
package-lock.json
generated
22
package-lock.json
generated
@ -111,6 +111,7 @@
|
|||||||
"micro": "^10.0.1",
|
"micro": "^10.0.1",
|
||||||
"next": "14.0.3",
|
"next": "14.0.3",
|
||||||
"next-auth": "4.24.5",
|
"next-auth": "4.24.5",
|
||||||
|
"next-axiom": "^1.1.1",
|
||||||
"next-plausible": "^3.10.1",
|
"next-plausible": "^3.10.1",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"perfect-freehand": "^1.2.0",
|
"perfect-freehand": "^1.2.0",
|
||||||
@ -16668,6 +16669,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/next-axiom": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/next-axiom/-/next-axiom-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-0r/TJ+/zetD+uDc7B+2E7WpC86hEtQ1U+DuWYrP/JNmUz+ZdPFbrZgzOSqaZ6TwYbXP56VVlPfYwq1YsKHTHYQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"remeda": "^1.29.0",
|
||||||
|
"whatwg-fetch": "^3.6.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"next": ">=13.4",
|
||||||
|
"react": ">=18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/next-contentlayer": {
|
"node_modules/next-contentlayer": {
|
||||||
"version": "0.3.4",
|
"version": "0.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/next-contentlayer/-/next-contentlayer-0.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/next-contentlayer/-/next-contentlayer-0.3.4.tgz",
|
||||||
@ -22936,6 +22953,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/whatwg-fetch": {
|
||||||
|
"version": "3.6.20",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz",
|
||||||
|
"integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="
|
||||||
|
},
|
||||||
"node_modules/whatwg-url": {
|
"node_modules/whatwg-url": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||||
|
|||||||
@ -3,8 +3,11 @@ import { prisma } from '@documenso/prisma';
|
|||||||
import type { DocumentAuditLog } from '@documenso/prisma/client';
|
import type { DocumentAuditLog } from '@documenso/prisma/client';
|
||||||
import type { Prisma } from '@documenso/prisma/client';
|
import type { Prisma } from '@documenso/prisma/client';
|
||||||
|
|
||||||
|
import { AppError } from '../../errors/app-error';
|
||||||
|
import type { TDocumentAuditLog } from '../../types/document-audit-logs';
|
||||||
import { DOCUMENT_AUDIT_LOG_TYPE } from '../../types/document-audit-logs';
|
import { DOCUMENT_AUDIT_LOG_TYPE } from '../../types/document-audit-logs';
|
||||||
import { parseDocumentAuditLogData } from '../../utils/document-audit-logs';
|
import { parseDocumentAuditLogData } from '../../utils/document-audit-logs';
|
||||||
|
import { buildServerLogger } from '../../utils/logger';
|
||||||
|
|
||||||
export interface FindDocumentAuditLogsOptions {
|
export interface FindDocumentAuditLogsOptions {
|
||||||
userId: number;
|
userId: number;
|
||||||
@ -97,7 +100,26 @@ export const findDocumentAuditLogs = async ({
|
|||||||
|
|
||||||
let nextCursor: string | undefined = undefined;
|
let nextCursor: string | undefined = undefined;
|
||||||
|
|
||||||
const parsedData = data.map((auditLog) => parseDocumentAuditLogData(auditLog));
|
let parsedData: TDocumentAuditLog[] = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
parsedData = data.map((auditLog) => parseDocumentAuditLogData(auditLog));
|
||||||
|
} catch (err) {
|
||||||
|
const error = AppError.parseError(err);
|
||||||
|
|
||||||
|
if (error.code === 'MIGRATION_REQUIRED') {
|
||||||
|
const logger = buildServerLogger();
|
||||||
|
|
||||||
|
logger.error('findDocumentAuditLogs', {
|
||||||
|
level: 'ALERT',
|
||||||
|
error,
|
||||||
|
});
|
||||||
|
|
||||||
|
void logger.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
if (parsedData.length > perPage) {
|
if (parsedData.length > perPage) {
|
||||||
const nextItem = parsedData.pop();
|
const nextItem = parsedData.pop();
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import type {
|
|||||||
} from '@documenso/prisma/client';
|
} from '@documenso/prisma/client';
|
||||||
|
|
||||||
import { RECIPIENT_ROLES_DESCRIPTION } from '../constants/recipient-roles';
|
import { RECIPIENT_ROLES_DESCRIPTION } from '../constants/recipient-roles';
|
||||||
|
import { AppError } from '../errors/app-error';
|
||||||
import type {
|
import type {
|
||||||
TDocumentAuditLog,
|
TDocumentAuditLog,
|
||||||
TDocumentAuditLogDocumentMetaDiffSchema,
|
TDocumentAuditLogDocumentMetaDiffSchema,
|
||||||
@ -69,7 +70,7 @@ export const parseDocumentAuditLogData = (auditLog: DocumentAuditLog): TDocument
|
|||||||
// Handle any required migrations here.
|
// Handle any required migrations here.
|
||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
console.error(data.error);
|
console.error(data.error);
|
||||||
throw new Error('Migration required');
|
throw new AppError('MIGRATION_REQUIRED');
|
||||||
}
|
}
|
||||||
|
|
||||||
return data.data;
|
return data.data;
|
||||||
|
|||||||
16
packages/lib/utils/logger.ts
Normal file
16
packages/lib/utils/logger.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import type { LoggerConfig } from 'next-axiom';
|
||||||
|
import { Logger } from 'next-axiom';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For usage in server-side code.
|
||||||
|
*
|
||||||
|
* When used in a server component, you must flush the logs.
|
||||||
|
*
|
||||||
|
* https://github.com/axiomhq/next-axiom?tab=readme-ov-file#server-components
|
||||||
|
*/
|
||||||
|
export const buildServerLogger = (config?: LoggerConfig) => {
|
||||||
|
return new Logger({
|
||||||
|
source: 'server',
|
||||||
|
...config,
|
||||||
|
});
|
||||||
|
};
|
||||||
@ -16,6 +16,7 @@ import { sendDocument } from '@documenso/lib/server-only/document/send-document'
|
|||||||
import { updateTitle } from '@documenso/lib/server-only/document/update-title';
|
import { updateTitle } from '@documenso/lib/server-only/document/update-title';
|
||||||
import { symmetricEncrypt } from '@documenso/lib/universal/crypto';
|
import { symmetricEncrypt } from '@documenso/lib/universal/crypto';
|
||||||
import { extractNextApiRequestMetadata } from '@documenso/lib/universal/extract-request-metadata';
|
import { extractNextApiRequestMetadata } from '@documenso/lib/universal/extract-request-metadata';
|
||||||
|
import { buildServerLogger } from '@documenso/lib/utils/logger';
|
||||||
|
|
||||||
import { authenticatedProcedure, procedure, router } from '../trpc';
|
import { authenticatedProcedure, procedure, router } from '../trpc';
|
||||||
import {
|
import {
|
||||||
@ -32,6 +33,12 @@ import {
|
|||||||
ZSetTitleForDocumentMutationSchema,
|
ZSetTitleForDocumentMutationSchema,
|
||||||
} from './schema';
|
} from './schema';
|
||||||
|
|
||||||
|
const logger = buildServerLogger({
|
||||||
|
args: {
|
||||||
|
context: 'trpcDocumentRouter',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const documentRouter = router({
|
export const documentRouter = router({
|
||||||
getDocumentById: authenticatedProcedure
|
getDocumentById: authenticatedProcedure
|
||||||
.input(ZGetDocumentByIdQuerySchema)
|
.input(ZGetDocumentByIdQuerySchema)
|
||||||
@ -42,6 +49,10 @@ export const documentRouter = router({
|
|||||||
userId: ctx.user.id,
|
userId: ctx.user.id,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
logger.error('getDocumentById', {
|
||||||
|
error: err,
|
||||||
|
});
|
||||||
|
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
@ -59,6 +70,10 @@ export const documentRouter = router({
|
|||||||
token,
|
token,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
logger.error('getDocumentByToken', {
|
||||||
|
error: err,
|
||||||
|
});
|
||||||
|
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
@ -77,6 +92,10 @@ export const documentRouter = router({
|
|||||||
userId: ctx.user.id,
|
userId: ctx.user.id,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
logger.error('getDocumentWithDetailsById', {
|
||||||
|
error: err,
|
||||||
|
});
|
||||||
|
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
@ -110,6 +129,10 @@ export const documentRouter = router({
|
|||||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
logger.error('createDocument', {
|
||||||
|
error: err,
|
||||||
|
});
|
||||||
|
|
||||||
if (err instanceof TRPCError) {
|
if (err instanceof TRPCError) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
@ -136,6 +159,10 @@ export const documentRouter = router({
|
|||||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
logger.error('deleteDocument', {
|
||||||
|
error: err,
|
||||||
|
});
|
||||||
|
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
@ -161,6 +188,10 @@ export const documentRouter = router({
|
|||||||
userId: ctx.user.id,
|
userId: ctx.user.id,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
logger.error('findDocumentAuditLogs', {
|
||||||
|
error: err,
|
||||||
|
});
|
||||||
|
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
@ -177,13 +208,21 @@ export const documentRouter = router({
|
|||||||
|
|
||||||
const userId = ctx.user.id;
|
const userId = ctx.user.id;
|
||||||
|
|
||||||
return await updateTitle({
|
try {
|
||||||
title,
|
return await updateTitle({
|
||||||
userId,
|
title,
|
||||||
teamId,
|
userId,
|
||||||
documentId,
|
teamId,
|
||||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
documentId,
|
||||||
});
|
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
logger.error('setTitleForDocument', {
|
||||||
|
error: err,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
setPasswordForDocument: authenticatedProcedure
|
setPasswordForDocument: authenticatedProcedure
|
||||||
@ -210,6 +249,10 @@ export const documentRouter = router({
|
|||||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
logger.error('setPasswordForDocument', {
|
||||||
|
error: err,
|
||||||
|
});
|
||||||
|
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
@ -245,6 +288,10 @@ export const documentRouter = router({
|
|||||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
logger.error('sendDocument', {
|
||||||
|
error: err,
|
||||||
|
});
|
||||||
|
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
@ -264,6 +311,10 @@ export const documentRouter = router({
|
|||||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
logger.error('resendDocument', {
|
||||||
|
error: err,
|
||||||
|
});
|
||||||
|
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
@ -282,6 +333,10 @@ export const documentRouter = router({
|
|||||||
...input,
|
...input,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
logger.error('duplicateDocument', {
|
||||||
|
error: err,
|
||||||
|
});
|
||||||
|
|
||||||
console.log(err);
|
console.log(err);
|
||||||
|
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
@ -302,7 +357,11 @@ export const documentRouter = router({
|
|||||||
userId: ctx.user.id,
|
userId: ctx.user.id,
|
||||||
});
|
});
|
||||||
return documents;
|
return documents;
|
||||||
} catch (error) {
|
} catch (err) {
|
||||||
|
logger.error('searchDocuments', {
|
||||||
|
error: err,
|
||||||
|
});
|
||||||
|
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: 'BAD_REQUEST',
|
code: 'BAD_REQUEST',
|
||||||
message: 'We are unable to search for documents. Please try again later.',
|
message: 'We are unable to search for documents. Please try again later.',
|
||||||
|
|||||||
@ -21,6 +21,10 @@ export const fieldRouter = router({
|
|||||||
try {
|
try {
|
||||||
const { documentId, fields } = input;
|
const { documentId, fields } = input;
|
||||||
|
|
||||||
|
if (Date.now() > 0) {
|
||||||
|
throw new Error('Some demo error');
|
||||||
|
}
|
||||||
|
|
||||||
return await setFieldsForDocument({
|
return await setFieldsForDocument({
|
||||||
documentId,
|
documentId,
|
||||||
userId: ctx.user.id,
|
userId: ctx.user.id,
|
||||||
@ -37,7 +41,10 @@ export const fieldRouter = router({
|
|||||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err, {
|
||||||
|
level: 'CRITICAL',
|
||||||
|
context: 'fieldRouter.addFields',
|
||||||
|
});
|
||||||
|
|
||||||
throw new TRPCError({
|
throw new TRPCError({
|
||||||
code: 'BAD_REQUEST',
|
code: 'BAD_REQUEST',
|
||||||
|
|||||||
Reference in New Issue
Block a user