mirror of
https://github.com/documenso/documenso.git
synced 2025-11-12 15:53:02 +10:00
feat: add field and recipient endpoints
This commit is contained in:
@ -4,14 +4,20 @@ import {
|
|||||||
ZSendDocumentForSigningMutationSchema as SendDocumentMutationSchema,
|
ZSendDocumentForSigningMutationSchema as SendDocumentMutationSchema,
|
||||||
ZAuthorizationHeadersSchema,
|
ZAuthorizationHeadersSchema,
|
||||||
ZCreateDocumentMutationSchema,
|
ZCreateDocumentMutationSchema,
|
||||||
|
ZCreateFieldMutationSchema,
|
||||||
ZCreateRecipientMutationSchema,
|
ZCreateRecipientMutationSchema,
|
||||||
ZDeleteDocumentMutationSchema,
|
ZDeleteDocumentMutationSchema,
|
||||||
|
ZDeleteFieldMutationSchema,
|
||||||
|
ZDeleteRecipientMutationSchema,
|
||||||
ZGetDocumentsQuerySchema,
|
ZGetDocumentsQuerySchema,
|
||||||
ZSuccessfulDocumentResponseSchema,
|
ZSuccessfulDocumentResponseSchema,
|
||||||
|
ZSuccessfulFieldResponseSchema,
|
||||||
ZSuccessfulRecipientResponseSchema,
|
ZSuccessfulRecipientResponseSchema,
|
||||||
ZSuccessfulResponseSchema,
|
ZSuccessfulResponseSchema,
|
||||||
ZSuccessfulSigningResponseSchema,
|
ZSuccessfulSigningResponseSchema,
|
||||||
ZUnsuccessfulResponseSchema,
|
ZUnsuccessfulResponseSchema,
|
||||||
|
ZUpdateFieldMutationSchema,
|
||||||
|
ZUpdateRecipientMutationSchema,
|
||||||
ZUploadDocumentSuccessfulSchema,
|
ZUploadDocumentSuccessfulSchema,
|
||||||
} from './schema';
|
} from './schema';
|
||||||
|
|
||||||
@ -93,6 +99,76 @@ export const ApiContractV1 = c.router(
|
|||||||
},
|
},
|
||||||
summary: 'Create a recipient for a document',
|
summary: 'Create a recipient for a document',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
updateRecipient: {
|
||||||
|
method: 'PATCH',
|
||||||
|
path: '/api/v1/documents/:id/recipients/:recipientId',
|
||||||
|
body: ZUpdateRecipientMutationSchema,
|
||||||
|
responses: {
|
||||||
|
200: ZSuccessfulRecipientResponseSchema,
|
||||||
|
400: ZUnsuccessfulResponseSchema,
|
||||||
|
401: ZUnsuccessfulResponseSchema,
|
||||||
|
404: ZUnsuccessfulResponseSchema,
|
||||||
|
500: ZUnsuccessfulResponseSchema,
|
||||||
|
},
|
||||||
|
summary: 'Update a recipient for a document',
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteRecipient: {
|
||||||
|
method: 'DELETE',
|
||||||
|
path: '/api/v1/documents/:id/recipients/:recipientId',
|
||||||
|
body: ZDeleteRecipientMutationSchema,
|
||||||
|
responses: {
|
||||||
|
200: ZSuccessfulRecipientResponseSchema,
|
||||||
|
400: ZUnsuccessfulResponseSchema,
|
||||||
|
401: ZUnsuccessfulResponseSchema,
|
||||||
|
404: ZUnsuccessfulResponseSchema,
|
||||||
|
500: ZUnsuccessfulResponseSchema,
|
||||||
|
},
|
||||||
|
summary: 'Delete a recipient from a document',
|
||||||
|
},
|
||||||
|
|
||||||
|
createField: {
|
||||||
|
method: 'POST',
|
||||||
|
path: '/api/v1/documents/:id/fields',
|
||||||
|
body: ZCreateFieldMutationSchema,
|
||||||
|
responses: {
|
||||||
|
200: ZSuccessfulFieldResponseSchema,
|
||||||
|
400: ZUnsuccessfulResponseSchema,
|
||||||
|
401: ZUnsuccessfulResponseSchema,
|
||||||
|
404: ZUnsuccessfulResponseSchema,
|
||||||
|
500: ZUnsuccessfulResponseSchema,
|
||||||
|
},
|
||||||
|
summary: 'Create a field for a document',
|
||||||
|
},
|
||||||
|
|
||||||
|
updateField: {
|
||||||
|
method: 'PATCH',
|
||||||
|
path: '/api/v1/documents/:id/fields/:fieldId',
|
||||||
|
body: ZUpdateFieldMutationSchema,
|
||||||
|
responses: {
|
||||||
|
200: ZSuccessfulFieldResponseSchema,
|
||||||
|
400: ZUnsuccessfulResponseSchema,
|
||||||
|
401: ZUnsuccessfulResponseSchema,
|
||||||
|
404: ZUnsuccessfulResponseSchema,
|
||||||
|
500: ZUnsuccessfulResponseSchema,
|
||||||
|
},
|
||||||
|
summary: 'Update a field for a document',
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteField: {
|
||||||
|
method: 'DELETE',
|
||||||
|
path: '/api/v1/documents/:id/fields/:fieldId',
|
||||||
|
body: ZDeleteFieldMutationSchema,
|
||||||
|
responses: {
|
||||||
|
200: ZSuccessfulFieldResponseSchema,
|
||||||
|
400: ZUnsuccessfulResponseSchema,
|
||||||
|
401: ZUnsuccessfulResponseSchema,
|
||||||
|
404: ZUnsuccessfulResponseSchema,
|
||||||
|
500: ZUnsuccessfulResponseSchema,
|
||||||
|
},
|
||||||
|
summary: 'Delete a field from a document',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
baseHeaders: ZAuthorizationHeadersSchema,
|
baseHeaders: ZAuthorizationHeadersSchema,
|
||||||
|
|||||||
@ -4,10 +4,17 @@ import { deleteDocument } from '@documenso/lib/server-only/document/delete-docum
|
|||||||
import { findDocuments } from '@documenso/lib/server-only/document/find-documents';
|
import { findDocuments } from '@documenso/lib/server-only/document/find-documents';
|
||||||
import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id';
|
import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id';
|
||||||
import { sendDocument } from '@documenso/lib/server-only/document/send-document';
|
import { sendDocument } from '@documenso/lib/server-only/document/send-document';
|
||||||
|
import { createField } from '@documenso/lib/server-only/field/create-field';
|
||||||
|
import { deleteField } from '@documenso/lib/server-only/field/delete-field';
|
||||||
|
import { getFieldById } from '@documenso/lib/server-only/field/get-field-by-id';
|
||||||
|
import { updateField } from '@documenso/lib/server-only/field/update-field';
|
||||||
|
import { deleteRecipient } from '@documenso/lib/server-only/recipient/delete-recipient';
|
||||||
|
import { getRecipientById } from '@documenso/lib/server-only/recipient/get-recipient-by-id';
|
||||||
import { getRecipientsForDocument } from '@documenso/lib/server-only/recipient/get-recipients-for-document';
|
import { getRecipientsForDocument } from '@documenso/lib/server-only/recipient/get-recipients-for-document';
|
||||||
import { setRecipientsForDocument } from '@documenso/lib/server-only/recipient/set-recipients-for-document';
|
import { setRecipientsForDocument } from '@documenso/lib/server-only/recipient/set-recipients-for-document';
|
||||||
|
import { updateRecipient } from '@documenso/lib/server-only/recipient/update-recipient';
|
||||||
import { getPresignPostUrl } from '@documenso/lib/universal/upload/server-actions';
|
import { getPresignPostUrl } from '@documenso/lib/universal/upload/server-actions';
|
||||||
import { DocumentStatus } from '@documenso/prisma/client';
|
import { DocumentStatus, SigningStatus } from '@documenso/prisma/client';
|
||||||
|
|
||||||
import { ApiContractV1 } from './contract';
|
import { ApiContractV1 } from './contract';
|
||||||
import { authenticatedMiddleware } from './middleware/authenticated';
|
import { authenticatedMiddleware } from './middleware/authenticated';
|
||||||
@ -250,4 +257,347 @@ export const ApiContractV1Implementation = createNextRoute(ApiContractV1, {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
updateRecipient: authenticatedMiddleware(async (args, user) => {
|
||||||
|
const { id: documentId, recipientId } = args.params;
|
||||||
|
const { name, email } = args.body;
|
||||||
|
|
||||||
|
const document = await getDocumentById({
|
||||||
|
id: Number(documentId),
|
||||||
|
userId: user.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!document) {
|
||||||
|
return {
|
||||||
|
status: 404,
|
||||||
|
body: {
|
||||||
|
message: 'Document not found',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.status === DocumentStatus.COMPLETED) {
|
||||||
|
return {
|
||||||
|
status: 400,
|
||||||
|
body: {
|
||||||
|
message: 'Document is already completed',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatedRecipient = await updateRecipient({
|
||||||
|
documentId: Number(documentId),
|
||||||
|
recipientId: Number(recipientId),
|
||||||
|
email,
|
||||||
|
name,
|
||||||
|
}).catch(() => null);
|
||||||
|
|
||||||
|
if (!updatedRecipient) {
|
||||||
|
return {
|
||||||
|
status: 404,
|
||||||
|
body: {
|
||||||
|
message: 'Recipient not found',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: updatedRecipient,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
deleteRecipient: authenticatedMiddleware(async (args, user) => {
|
||||||
|
const { id: documentId, recipientId } = args.params;
|
||||||
|
|
||||||
|
const document = await getDocumentById({
|
||||||
|
id: Number(documentId),
|
||||||
|
userId: user.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!document) {
|
||||||
|
return {
|
||||||
|
status: 404,
|
||||||
|
body: {
|
||||||
|
message: 'Document not found',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.status === DocumentStatus.COMPLETED) {
|
||||||
|
return {
|
||||||
|
status: 400,
|
||||||
|
body: {
|
||||||
|
message: 'Document is already completed',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const deletedRecipient = await deleteRecipient({
|
||||||
|
documentId: Number(documentId),
|
||||||
|
recipientId: Number(recipientId),
|
||||||
|
}).catch(() => null);
|
||||||
|
|
||||||
|
if (!deletedRecipient) {
|
||||||
|
return {
|
||||||
|
status: 400,
|
||||||
|
body: {
|
||||||
|
message: 'Unable to delete recipient',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: deletedRecipient,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
createField: authenticatedMiddleware(async (args, user) => {
|
||||||
|
const { id: documentId } = args.params;
|
||||||
|
const { recipientId, type, pageNumber, pageWidth, pageHeight, pageX, pageY } = args.body;
|
||||||
|
|
||||||
|
const document = await getDocumentById({
|
||||||
|
id: Number(documentId),
|
||||||
|
userId: user.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!document) {
|
||||||
|
return {
|
||||||
|
status: 404,
|
||||||
|
body: {
|
||||||
|
message: 'Document not found',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.status === DocumentStatus.COMPLETED) {
|
||||||
|
return {
|
||||||
|
status: 400,
|
||||||
|
body: {
|
||||||
|
message: 'Document is already completed',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const recipient = await getRecipientById({
|
||||||
|
id: Number(recipientId),
|
||||||
|
documentId: Number(documentId),
|
||||||
|
}).catch(() => null);
|
||||||
|
|
||||||
|
if (!recipient) {
|
||||||
|
return {
|
||||||
|
status: 404,
|
||||||
|
body: {
|
||||||
|
message: 'Recipient not found',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recipient.signingStatus === SigningStatus.SIGNED) {
|
||||||
|
return {
|
||||||
|
status: 400,
|
||||||
|
body: {
|
||||||
|
message: 'Recipient has already signed the document',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const field = await createField({
|
||||||
|
documentId: Number(documentId),
|
||||||
|
recipientId: Number(recipientId),
|
||||||
|
type,
|
||||||
|
pageNumber,
|
||||||
|
pageX,
|
||||||
|
pageY,
|
||||||
|
pageWidth,
|
||||||
|
pageHeight,
|
||||||
|
});
|
||||||
|
|
||||||
|
const remappedField = {
|
||||||
|
documentId: field.documentId,
|
||||||
|
recipientId: field.recipientId ?? -1,
|
||||||
|
type: field.type,
|
||||||
|
pageNumber: field.page,
|
||||||
|
pageX: Number(field.positionX),
|
||||||
|
pageY: Number(field.positionY),
|
||||||
|
pageWidth: Number(field.width),
|
||||||
|
pageHeight: Number(field.height),
|
||||||
|
customText: field.customText,
|
||||||
|
inserted: field.inserted,
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: remappedField,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
updateField: authenticatedMiddleware(async (args, user) => {
|
||||||
|
const { id: documentId, fieldId } = args.params;
|
||||||
|
const { recipientId, type, pageNumber, pageWidth, pageHeight, pageX, pageY } = args.body;
|
||||||
|
|
||||||
|
const document = await getDocumentById({
|
||||||
|
id: Number(documentId),
|
||||||
|
userId: user.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!document) {
|
||||||
|
return {
|
||||||
|
status: 404,
|
||||||
|
body: {
|
||||||
|
message: 'Document not found',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.status === DocumentStatus.COMPLETED) {
|
||||||
|
return {
|
||||||
|
status: 400,
|
||||||
|
body: {
|
||||||
|
message: 'Document is already completed',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const recipient = await getRecipientById({
|
||||||
|
id: Number(recipientId),
|
||||||
|
documentId: Number(documentId),
|
||||||
|
}).catch(() => null);
|
||||||
|
|
||||||
|
if (!recipient) {
|
||||||
|
return {
|
||||||
|
status: 404,
|
||||||
|
body: {
|
||||||
|
message: 'Recipient not found',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recipient.signingStatus === SigningStatus.SIGNED) {
|
||||||
|
return {
|
||||||
|
status: 400,
|
||||||
|
body: {
|
||||||
|
message: 'Recipient has already signed the document',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatedField = await updateField({
|
||||||
|
fieldId: Number(fieldId),
|
||||||
|
documentId: Number(documentId),
|
||||||
|
recipientId: recipientId ? Number(recipientId) : undefined,
|
||||||
|
type,
|
||||||
|
pageNumber,
|
||||||
|
pageX,
|
||||||
|
pageY,
|
||||||
|
pageWidth,
|
||||||
|
pageHeight,
|
||||||
|
});
|
||||||
|
|
||||||
|
const remappedField = {
|
||||||
|
documentId: updatedField.documentId,
|
||||||
|
recipientId: updatedField.recipientId ?? -1,
|
||||||
|
type: updatedField.type,
|
||||||
|
pageNumber: updatedField.page,
|
||||||
|
pageX: Number(updatedField.positionX),
|
||||||
|
pageY: Number(updatedField.positionY),
|
||||||
|
pageWidth: Number(updatedField.width),
|
||||||
|
pageHeight: Number(updatedField.height),
|
||||||
|
customText: updatedField.customText,
|
||||||
|
inserted: updatedField.inserted,
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: remappedField,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
deleteField: authenticatedMiddleware(async (args, user) => {
|
||||||
|
const { id: documentId, fieldId } = args.params;
|
||||||
|
|
||||||
|
const document = await getDocumentById({
|
||||||
|
id: Number(documentId),
|
||||||
|
userId: user.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!document) {
|
||||||
|
return {
|
||||||
|
status: 404,
|
||||||
|
body: {
|
||||||
|
message: 'Document not found',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.status === DocumentStatus.COMPLETED) {
|
||||||
|
return {
|
||||||
|
status: 400,
|
||||||
|
body: {
|
||||||
|
message: 'Document is already completed',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const field = await getFieldById({
|
||||||
|
fieldId: Number(fieldId),
|
||||||
|
documentId: Number(documentId),
|
||||||
|
}).catch(() => null);
|
||||||
|
|
||||||
|
if (!field) {
|
||||||
|
return {
|
||||||
|
status: 404,
|
||||||
|
body: {
|
||||||
|
message: 'Field not found',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const recipient = await getRecipientById({
|
||||||
|
id: Number(field.recipientId),
|
||||||
|
documentId: Number(documentId),
|
||||||
|
}).catch(() => null);
|
||||||
|
|
||||||
|
if (recipient?.signingStatus === SigningStatus.SIGNED) {
|
||||||
|
return {
|
||||||
|
status: 400,
|
||||||
|
body: {
|
||||||
|
message: 'Recipient has already signed the document',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const deletedField = await deleteField({
|
||||||
|
documentId: Number(documentId),
|
||||||
|
fieldId: Number(fieldId),
|
||||||
|
}).catch(() => null);
|
||||||
|
|
||||||
|
if (!deletedField) {
|
||||||
|
return {
|
||||||
|
status: 400,
|
||||||
|
body: {
|
||||||
|
message: 'Unable to delete field',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const remappedField = {
|
||||||
|
documentId: deletedField.documentId,
|
||||||
|
recipientId: deletedField.recipientId ?? -1,
|
||||||
|
type: deletedField.type,
|
||||||
|
pageNumber: deletedField.page,
|
||||||
|
pageX: Number(deletedField.positionX),
|
||||||
|
pageY: Number(deletedField.positionY),
|
||||||
|
pageWidth: Number(deletedField.width),
|
||||||
|
pageHeight: Number(deletedField.height),
|
||||||
|
customText: deletedField.customText,
|
||||||
|
inserted: deletedField.inserted,
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: remappedField,
|
||||||
|
};
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { ReadStatus, SendStatus, SigningStatus } from '@documenso/prisma/client';
|
import { FieldType, ReadStatus, SendStatus, SigningStatus } from '@documenso/prisma/client';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Documents
|
||||||
|
*/
|
||||||
export const ZGetDocumentsQuerySchema = z.object({
|
export const ZGetDocumentsQuerySchema = z.object({
|
||||||
page: z.string().optional(),
|
page: z.string().optional(),
|
||||||
perPage: z.string().optional(),
|
perPage: z.string().optional(),
|
||||||
@ -49,8 +52,19 @@ export const ZCreateRecipientMutationSchema = z.object({
|
|||||||
email: z.string().email().min(1),
|
email: z.string().email().min(1),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recipients
|
||||||
|
*/
|
||||||
export type TCreateRecipientMutationSchema = z.infer<typeof ZCreateRecipientMutationSchema>;
|
export type TCreateRecipientMutationSchema = z.infer<typeof ZCreateRecipientMutationSchema>;
|
||||||
|
|
||||||
|
export const ZUpdateRecipientMutationSchema = ZCreateRecipientMutationSchema.partial();
|
||||||
|
|
||||||
|
export type TUpdateRecipientMutationSchema = z.infer<typeof ZUpdateRecipientMutationSchema>;
|
||||||
|
|
||||||
|
export const ZDeleteRecipientMutationSchema = null;
|
||||||
|
|
||||||
|
export type TDeleteRecipientMutationSchema = typeof ZDeleteRecipientMutationSchema;
|
||||||
|
|
||||||
export const ZSuccessfulRecipientResponseSchema = z.object({
|
export const ZSuccessfulRecipientResponseSchema = z.object({
|
||||||
id: z.number(),
|
id: z.number(),
|
||||||
documentId: z.number(),
|
documentId: z.number(),
|
||||||
@ -67,6 +81,44 @@ export const ZSuccessfulRecipientResponseSchema = z.object({
|
|||||||
|
|
||||||
export type TSuccessfulRecipientResponseSchema = z.infer<typeof ZSuccessfulRecipientResponseSchema>;
|
export type TSuccessfulRecipientResponseSchema = z.infer<typeof ZSuccessfulRecipientResponseSchema>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fields
|
||||||
|
*/
|
||||||
|
export const ZCreateFieldMutationSchema = z.object({
|
||||||
|
recipientId: z.number(),
|
||||||
|
type: z.nativeEnum(FieldType),
|
||||||
|
pageNumber: z.number(),
|
||||||
|
pageX: z.number(),
|
||||||
|
pageY: z.number(),
|
||||||
|
pageWidth: z.number(),
|
||||||
|
pageHeight: z.number(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TCreateFieldMutationSchema = z.infer<typeof ZCreateFieldMutationSchema>;
|
||||||
|
|
||||||
|
export const ZUpdateFieldMutationSchema = ZCreateFieldMutationSchema.partial();
|
||||||
|
|
||||||
|
export type TUpdateFieldMutationSchema = z.infer<typeof ZUpdateFieldMutationSchema>;
|
||||||
|
|
||||||
|
export const ZDeleteFieldMutationSchema = null;
|
||||||
|
|
||||||
|
export type TDeleteFieldMutationSchema = typeof ZDeleteFieldMutationSchema;
|
||||||
|
|
||||||
|
export const ZSuccessfulFieldResponseSchema = z.object({
|
||||||
|
documentId: z.number(),
|
||||||
|
recipientId: z.number(),
|
||||||
|
type: z.nativeEnum(FieldType),
|
||||||
|
pageNumber: z.number(),
|
||||||
|
pageX: z.number(),
|
||||||
|
pageY: z.number(),
|
||||||
|
pageWidth: z.number(),
|
||||||
|
pageHeight: z.number(),
|
||||||
|
customText: z.string(),
|
||||||
|
inserted: z.boolean(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TSuccessfulFieldResponseSchema = z.infer<typeof ZSuccessfulFieldResponseSchema>;
|
||||||
|
|
||||||
export const ZSuccessfulResponseSchema = z.object({
|
export const ZSuccessfulResponseSchema = z.object({
|
||||||
documents: ZSuccessfulDocumentResponseSchema.array(),
|
documents: ZSuccessfulDocumentResponseSchema.array(),
|
||||||
totalPages: z.number(),
|
totalPages: z.number(),
|
||||||
@ -80,14 +132,17 @@ export const ZSuccessfulSigningResponseSchema = z.object({
|
|||||||
|
|
||||||
export type TSuccessfulSigningResponseSchema = z.infer<typeof ZSuccessfulSigningResponseSchema>;
|
export type TSuccessfulSigningResponseSchema = z.infer<typeof ZSuccessfulSigningResponseSchema>;
|
||||||
|
|
||||||
export const ZUnsuccessfulResponseSchema = z.object({
|
/**
|
||||||
message: z.string(),
|
* General
|
||||||
});
|
*/
|
||||||
|
|
||||||
export type TUnsuccessfulResponseSchema = z.infer<typeof ZUnsuccessfulResponseSchema>;
|
|
||||||
|
|
||||||
export const ZAuthorizationHeadersSchema = z.object({
|
export const ZAuthorizationHeadersSchema = z.object({
|
||||||
authorization: z.string(),
|
authorization: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TAuthorizationHeadersSchema = z.infer<typeof ZAuthorizationHeadersSchema>;
|
export type TAuthorizationHeadersSchema = z.infer<typeof ZAuthorizationHeadersSchema>;
|
||||||
|
|
||||||
|
export const ZUnsuccessfulResponseSchema = z.object({
|
||||||
|
message: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TUnsuccessfulResponseSchema = z.infer<typeof ZUnsuccessfulResponseSchema>;
|
||||||
|
|||||||
41
packages/lib/server-only/field/create-field.ts
Normal file
41
packages/lib/server-only/field/create-field.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { prisma } from '@documenso/prisma';
|
||||||
|
import type { FieldType } from '@documenso/prisma/client';
|
||||||
|
|
||||||
|
export type CreateFieldOptions = {
|
||||||
|
documentId: number;
|
||||||
|
recipientId: number;
|
||||||
|
type: FieldType;
|
||||||
|
pageNumber: number;
|
||||||
|
pageX: number;
|
||||||
|
pageY: number;
|
||||||
|
pageWidth: number;
|
||||||
|
pageHeight: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createField = async ({
|
||||||
|
documentId,
|
||||||
|
recipientId,
|
||||||
|
type,
|
||||||
|
pageNumber,
|
||||||
|
pageX,
|
||||||
|
pageY,
|
||||||
|
pageWidth,
|
||||||
|
pageHeight,
|
||||||
|
}: CreateFieldOptions) => {
|
||||||
|
const field = await prisma.field.create({
|
||||||
|
data: {
|
||||||
|
documentId,
|
||||||
|
recipientId,
|
||||||
|
type,
|
||||||
|
page: pageNumber,
|
||||||
|
positionX: pageX,
|
||||||
|
positionY: pageY,
|
||||||
|
width: pageWidth,
|
||||||
|
height: pageHeight,
|
||||||
|
customText: '',
|
||||||
|
inserted: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return field;
|
||||||
|
};
|
||||||
17
packages/lib/server-only/field/delete-field.ts
Normal file
17
packages/lib/server-only/field/delete-field.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { prisma } from '@documenso/prisma';
|
||||||
|
|
||||||
|
export type DeleteFieldOptions = {
|
||||||
|
fieldId: number;
|
||||||
|
documentId: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteField = async ({ fieldId, documentId }: DeleteFieldOptions) => {
|
||||||
|
const field = await prisma.field.delete({
|
||||||
|
where: {
|
||||||
|
id: fieldId,
|
||||||
|
documentId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return field;
|
||||||
|
};
|
||||||
17
packages/lib/server-only/field/get-field-by-id.ts
Normal file
17
packages/lib/server-only/field/get-field-by-id.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { prisma } from '@documenso/prisma';
|
||||||
|
|
||||||
|
export type GetFieldByIdOptions = {
|
||||||
|
fieldId: number;
|
||||||
|
documentId: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getFieldById = async ({ fieldId, documentId }: GetFieldByIdOptions) => {
|
||||||
|
const field = await prisma.field.findFirst({
|
||||||
|
where: {
|
||||||
|
id: fieldId,
|
||||||
|
documentId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return field;
|
||||||
|
};
|
||||||
44
packages/lib/server-only/field/update-field.ts
Normal file
44
packages/lib/server-only/field/update-field.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { prisma } from '@documenso/prisma';
|
||||||
|
import type { FieldType } from '@documenso/prisma/client';
|
||||||
|
|
||||||
|
export type UpdateFieldOptions = {
|
||||||
|
fieldId: number;
|
||||||
|
documentId: number;
|
||||||
|
recipientId?: number;
|
||||||
|
type?: FieldType;
|
||||||
|
pageNumber?: number;
|
||||||
|
pageX?: number;
|
||||||
|
pageY?: number;
|
||||||
|
pageWidth?: number;
|
||||||
|
pageHeight?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateField = async ({
|
||||||
|
fieldId,
|
||||||
|
documentId,
|
||||||
|
recipientId,
|
||||||
|
type,
|
||||||
|
pageNumber,
|
||||||
|
pageX,
|
||||||
|
pageY,
|
||||||
|
pageWidth,
|
||||||
|
pageHeight,
|
||||||
|
}: UpdateFieldOptions) => {
|
||||||
|
const field = await prisma.field.update({
|
||||||
|
where: {
|
||||||
|
id: fieldId,
|
||||||
|
documentId,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
recipientId,
|
||||||
|
type,
|
||||||
|
page: pageNumber,
|
||||||
|
positionX: pageX,
|
||||||
|
positionY: pageY,
|
||||||
|
width: pageWidth,
|
||||||
|
height: pageHeight,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return field;
|
||||||
|
};
|
||||||
32
packages/lib/server-only/recipient/delete-recipient.ts
Normal file
32
packages/lib/server-only/recipient/delete-recipient.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { prisma } from '@documenso/prisma';
|
||||||
|
import { SendStatus } from '@documenso/prisma/client';
|
||||||
|
|
||||||
|
export type DeleteRecipientOptions = {
|
||||||
|
documentId: number;
|
||||||
|
recipientId: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteRecipient = async ({ documentId, recipientId }: DeleteRecipientOptions) => {
|
||||||
|
const recipient = await prisma.recipient.findFirst({
|
||||||
|
where: {
|
||||||
|
id: recipientId,
|
||||||
|
documentId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!recipient) {
|
||||||
|
throw new Error('Recipient not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recipient.sendStatus !== SendStatus.NOT_SENT) {
|
||||||
|
throw new Error('Can not delete a recipient that has already been sent a document');
|
||||||
|
}
|
||||||
|
|
||||||
|
const deletedRecipient = await prisma.recipient.delete({
|
||||||
|
where: {
|
||||||
|
id: recipient.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return deletedRecipient;
|
||||||
|
};
|
||||||
21
packages/lib/server-only/recipient/get-recipient-by-email.ts
Normal file
21
packages/lib/server-only/recipient/get-recipient-by-email.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { prisma } from '@documenso/prisma';
|
||||||
|
|
||||||
|
export type GetRecipientByEmailOptions = {
|
||||||
|
documentId: number;
|
||||||
|
email: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getRecipientByEmail = async ({ documentId, email }: GetRecipientByEmailOptions) => {
|
||||||
|
const recipient = await prisma.recipient.findFirst({
|
||||||
|
where: {
|
||||||
|
documentId,
|
||||||
|
email: email.toLowerCase(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!recipient) {
|
||||||
|
throw new Error('Recipient not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
return recipient;
|
||||||
|
};
|
||||||
21
packages/lib/server-only/recipient/get-recipient-by-id.ts
Normal file
21
packages/lib/server-only/recipient/get-recipient-by-id.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { prisma } from '@documenso/prisma';
|
||||||
|
|
||||||
|
export type GetRecipientByIdOptions = {
|
||||||
|
id: number;
|
||||||
|
documentId: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getRecipientById = async ({ documentId, id }: GetRecipientByIdOptions) => {
|
||||||
|
const recipient = await prisma.recipient.findFirst({
|
||||||
|
where: {
|
||||||
|
documentId,
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!recipient) {
|
||||||
|
throw new Error('Recipient not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
return recipient;
|
||||||
|
};
|
||||||
38
packages/lib/server-only/recipient/update-recipient.ts
Normal file
38
packages/lib/server-only/recipient/update-recipient.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { prisma } from '@documenso/prisma';
|
||||||
|
|
||||||
|
export type UpdateRecipientOptions = {
|
||||||
|
documentId: number;
|
||||||
|
recipientId: number;
|
||||||
|
email?: string;
|
||||||
|
name?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateRecipient = async ({
|
||||||
|
documentId,
|
||||||
|
recipientId,
|
||||||
|
email,
|
||||||
|
name,
|
||||||
|
}: UpdateRecipientOptions) => {
|
||||||
|
const recipient = await prisma.recipient.findFirst({
|
||||||
|
where: {
|
||||||
|
id: recipientId,
|
||||||
|
documentId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!recipient) {
|
||||||
|
throw new Error('Recipient not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatedRecipient = await prisma.recipient.update({
|
||||||
|
where: {
|
||||||
|
id: recipient.id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
email: email?.toLowerCase() ?? recipient.email,
|
||||||
|
name: name ?? recipient.name,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return updatedRecipient;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user