Files
sign/packages/lib/server-only/field/create-field.ts

176 lines
3.8 KiB
TypeScript
Raw Normal View History

import { match } from 'ts-pattern';
import { prisma } from '@documenso/prisma';
2024-02-22 13:39:34 +11:00
import type { FieldType, Team } from '@documenso/prisma/client';
import {
ZCheckboxFieldMeta,
ZDropdownFieldMeta,
ZNumberFieldMeta,
ZRadioFieldMeta,
ZTextFieldMeta,
} from '../../types/field-meta';
import type { TFieldMetaSchema as FieldMeta } from '../../types/field-meta';
2024-02-22 13:39:34 +11:00
import type { RequestMetadata } from '../../universal/extract-request-metadata';
import { createDocumentAuditLogData } from '../../utils/document-audit-logs';
export type CreateFieldOptions = {
documentId: number;
2024-02-22 13:39:34 +11:00
userId: number;
teamId?: number;
recipientId: number;
type: FieldType;
pageNumber: number;
pageX: number;
pageY: number;
pageWidth: number;
pageHeight: number;
fieldMeta?: FieldMeta;
2024-02-22 13:39:34 +11:00
requestMetadata?: RequestMetadata;
};
export const createField = async ({
documentId,
2024-02-22 13:39:34 +11:00
userId,
teamId,
recipientId,
type,
pageNumber,
pageX,
pageY,
pageWidth,
pageHeight,
fieldMeta,
2024-02-22 13:39:34 +11:00
requestMetadata,
}: CreateFieldOptions) => {
2024-02-22 13:39:34 +11:00
const document = await prisma.document.findFirst({
select: {
id: true,
},
where: {
id: documentId,
...(teamId
? {
team: {
id: teamId,
members: {
some: {
userId,
},
},
},
}
: {
userId,
teamId: null,
}),
},
});
if (!document) {
throw new Error('Document not found');
}
const user = await prisma.user.findFirstOrThrow({
where: {
id: userId,
},
select: {
id: true,
name: true,
email: true,
},
});
let team: Team | null = null;
if (teamId) {
team = await prisma.team.findFirst({
where: {
id: teamId,
members: {
some: {
userId,
},
},
},
});
}
const advancedField = ['NUMBER', 'RADIO', 'CHECKBOX', 'DROPDOWN', 'TEXT'].includes(type);
if (advancedField && !fieldMeta) {
throw new Error(
'Field meta is required for this type of field. Please provide the appropriate field meta object.',
);
}
if (fieldMeta && fieldMeta.type.toLowerCase() !== String(type).toLowerCase()) {
throw new Error('Field meta type does not match the field type');
}
const result = match(type)
.with('RADIO', () => {
return ZRadioFieldMeta.safeParse(fieldMeta);
})
.with('CHECKBOX', () => {
return ZCheckboxFieldMeta.safeParse(fieldMeta);
})
.with('DROPDOWN', () => {
return ZDropdownFieldMeta.safeParse(fieldMeta);
})
.with('NUMBER', () => {
return ZNumberFieldMeta.safeParse(fieldMeta);
})
.with('TEXT', () => {
return ZTextFieldMeta.safeParse(fieldMeta);
})
.otherwise(() => {
return { success: false, data: {} };
});
if (!result.success) {
throw new Error('Field meta parsing failed');
}
const field = await prisma.field.create({
data: {
documentId,
recipientId,
type,
page: pageNumber,
positionX: pageX,
positionY: pageY,
width: pageWidth,
height: pageHeight,
customText: '',
inserted: false,
fieldMeta: advancedField ? result.data : undefined,
},
2024-02-22 13:39:34 +11:00
include: {
Recipient: true,
},
});
await prisma.documentAuditLog.create({
data: createDocumentAuditLogData({
type: 'FIELD_CREATED',
documentId,
user: {
id: team?.id ?? user.id,
email: team?.name ?? user.email,
name: team ? '' : user.name,
},
data: {
fieldId: field.secondaryId,
fieldRecipientEmail: field.Recipient?.email ?? '',
fieldRecipientId: recipientId,
fieldType: field.type,
},
requestMetadata,
}),
});
return field;
};