fix: merge conflicts

This commit is contained in:
Ephraim Atta-Duncan
2025-10-20 14:54:42 +00:00
448 changed files with 33524 additions and 9229 deletions

View File

@ -657,7 +657,7 @@ export const ZDocumentAuditLogEventRecipientExpiryExtendedSchema = z.object({
export const ZDocumentAuditLogBaseSchema = z.object({
id: z.string(),
createdAt: z.date(),
documentId: z.number(),
envelopeId: z.string(),
name: z.string().optional().nullable(),
email: z.string().optional().nullable(),
userId: z.number().optional().nullable(),

View File

@ -1,8 +1,14 @@
import { msg } from '@lingui/core/macro';
import { DocumentDistributionMethod, DocumentSigningOrder } from '@prisma/client';
import { z } from 'zod';
import { VALID_DATE_FORMAT_VALUES } from '@documenso/lib/constants/date-formats';
import { SUPPORTED_LANGUAGE_CODES } from '@documenso/lib/constants/i18n';
import { isValidRedirectUrl } from '@documenso/lib/utils/is-valid-redirect-url';
import { DocumentMetaSchema } from '@documenso/prisma/generated/zod/modelSchema/DocumentMetaSchema';
import { ZDocumentEmailSettingsSchema } from './document-email';
/**
* The full document response schema.
*
@ -15,9 +21,7 @@ export const ZDocumentMetaSchema = DocumentMetaSchema.pick({
subject: true,
message: true,
timezone: true,
password: true,
dateFormat: true,
documentId: true,
redirectUrl: true,
typedSignatureEnabled: true,
uploadSignatureEnabled: true,
@ -51,3 +55,99 @@ export const ZDocumentSignatureSettingsSchema = z
);
export type TDocumentSignatureSettings = z.infer<typeof ZDocumentSignatureSettingsSchema>;
export const ZDocumentMetaTimezoneSchema = z
.string()
.describe(
'The timezone to use for date fields and signing the document. Example Etc/UTC, Australia/Melbourne',
);
export type TDocumentMetaTimezone = z.infer<typeof ZDocumentMetaTimezoneSchema>;
export const ZDocumentMetaDateFormatSchema = z
.enum(VALID_DATE_FORMAT_VALUES)
.describe('The date format to use for date fields and signing the document.');
export type TDocumentMetaDateFormat = z.infer<typeof ZDocumentMetaDateFormatSchema>;
export const ZDocumentMetaRedirectUrlSchema = z
.string()
.describe('The URL to which the recipient should be redirected after signing the document.')
.refine((value) => value === undefined || value === '' || isValidRedirectUrl(value), {
message: 'Please enter a valid URL, make sure you include http:// or https:// part of the url.',
});
export const ZDocumentMetaLanguageSchema = z
.enum(SUPPORTED_LANGUAGE_CODES)
.describe('The language to use for email communications with recipients.');
export const ZDocumentMetaSubjectSchema = z
.string()
.max(254)
.describe('The subject of the email that will be sent to the recipients.');
export const ZDocumentMetaMessageSchema = z
.string()
.max(5000)
.describe('The message of the email that will be sent to the recipients.');
export const ZDocumentMetaDistributionMethodSchema = z
.nativeEnum(DocumentDistributionMethod)
.describe('The distribution method to use when sending the document to the recipients.');
export const ZDocumentMetaTypedSignatureEnabledSchema = z
.boolean()
.describe('Whether to allow recipients to sign using a typed signature.');
export const ZDocumentMetaDrawSignatureEnabledSchema = z
.boolean()
.describe('Whether to allow recipients to sign using a draw signature.');
export const ZDocumentMetaUploadSignatureEnabledSchema = z
.boolean()
.describe('Whether to allow recipients to sign using an uploaded signature.');
export const ZDocumentExpiryAmountSchema = z
.number()
.int()
.min(1)
.describe('The amount for expiry duration (e.g., 3 for "3 days").');
export const ZDocumentExpiryUnitSchema = z
.enum(['minutes', 'hours', 'days', 'weeks', 'months'])
.describe('The unit for expiry duration (e.g., "days" for "3 days").');
/**
* Note: Any updates to this will cause public API changes. You will need to update
* all corresponding areas where this is used (some places that use this needs to pass
* it through to another function).
*/
export const ZDocumentMetaCreateSchema = z.object({
subject: ZDocumentMetaSubjectSchema.optional(),
message: ZDocumentMetaMessageSchema.optional(),
timezone: ZDocumentMetaTimezoneSchema.optional(),
dateFormat: ZDocumentMetaDateFormatSchema.optional(),
distributionMethod: ZDocumentMetaDistributionMethodSchema.optional(),
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
allowDictateNextSigner: z.boolean().optional(),
redirectUrl: ZDocumentMetaRedirectUrlSchema.optional(),
language: ZDocumentMetaLanguageSchema.optional(),
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
emailId: z.string().nullish(),
emailReplyTo: z.string().email().nullish(),
emailSettings: ZDocumentEmailSettingsSchema.optional(),
expiryAmount: ZDocumentExpiryAmountSchema.optional(),
expiryUnit: ZDocumentExpiryUnitSchema.optional(),
});
export type TDocumentMetaCreate = z.infer<typeof ZDocumentMetaCreateSchema>;
/**
* Note: This is the same as the create schema for now since there are
* no nullable values. Once there is we will need to update this properly.
*/
export const ZDocumentMetaUpdateSchema = ZDocumentMetaCreateSchema;
export type TDocumentMetaUpdate = z.infer<typeof ZDocumentMetaUpdateSchema>;

View File

@ -1,11 +1,11 @@
import type { z } from 'zod';
import { z } from 'zod';
import { DocumentDataSchema } from '@documenso/prisma/generated/zod/modelSchema/DocumentDataSchema';
import { DocumentMetaSchema } from '@documenso/prisma/generated/zod/modelSchema/DocumentMetaSchema';
import { DocumentSchema } from '@documenso/prisma/generated/zod/modelSchema/DocumentSchema';
import { FolderSchema } from '@documenso/prisma/generated/zod/modelSchema/FolderSchema';
import { TeamSchema } from '@documenso/prisma/generated/zod/modelSchema/TeamSchema';
import { UserSchema } from '@documenso/prisma/generated/zod/modelSchema/UserSchema';
import { LegacyDocumentSchema } from '@documenso/prisma/types/document-legacy-schema';
import { ZFieldSchema } from './field';
import { ZRecipientLiteSchema } from './recipient';
@ -15,7 +15,7 @@ import { ZRecipientLiteSchema } from './recipient';
*
* Mainly used for returning a single document from the API.
*/
export const ZDocumentSchema = DocumentSchema.pick({
export const ZDocumentSchema = LegacyDocumentSchema.pick({
visibility: true,
status: true,
source: true,
@ -25,21 +25,32 @@ export const ZDocumentSchema = DocumentSchema.pick({
authOptions: true,
formValues: true,
title: true,
documentDataId: true,
createdAt: true,
updatedAt: true,
completedAt: true,
deletedAt: true,
teamId: true,
templateId: true,
folderId: true,
}).extend({
envelopeId: z.string(),
// Which "Template" the document was created from.
templateId: z
.number()
.nullish()
.describe('The ID of the template that the document was created from, if any.'),
// Backwards compatibility.
documentDataId: z.string().default(''),
// Todo: Maybe we want to alter this a bit since this returns a lot of data.
documentData: DocumentDataSchema.pick({
type: true,
id: true,
data: true,
initialData: true,
}).extend({
envelopeItemId: z.string(),
}),
documentMeta: DocumentMetaSchema.pick({
signingOrder: true,
@ -48,9 +59,7 @@ export const ZDocumentSchema = DocumentSchema.pick({
subject: true,
message: true,
timezone: true,
password: true,
dateFormat: true,
documentId: true,
redirectUrl: true,
typedSignatureEnabled: true,
uploadSignatureEnabled: true,
@ -62,7 +71,11 @@ export const ZDocumentSchema = DocumentSchema.pick({
emailReplyTo: true,
expiryAmount: true,
expiryUnit: true,
}).nullable(),
}).extend({
password: z.string().nullable().default(null),
documentId: z.number().default(-1).optional(),
}),
folder: FolderSchema.pick({
id: true,
name: true,
@ -84,7 +97,7 @@ export type TDocument = z.infer<typeof ZDocumentSchema>;
/**
* A lite version of the document response schema without relations.
*/
export const ZDocumentLiteSchema = DocumentSchema.pick({
export const ZDocumentLiteSchema = LegacyDocumentSchema.pick({
visibility: true,
status: true,
source: true,
@ -94,15 +107,24 @@ export const ZDocumentLiteSchema = DocumentSchema.pick({
authOptions: true,
formValues: true,
title: true,
documentDataId: true,
createdAt: true,
updatedAt: true,
completedAt: true,
deletedAt: true,
teamId: true,
templateId: true,
folderId: true,
useLegacyFieldInsertion: true,
}).extend({
envelopeId: z.string(),
// Backwards compatibility.
documentDataId: z.string().default(''),
// Which "Template" the document was created from.
templateId: z
.number()
.nullish()
.describe('The ID of the template that the document was created from, if any.'),
});
export type TDocumentLite = z.infer<typeof ZDocumentLiteSchema>;
@ -110,7 +132,7 @@ export type TDocumentLite = z.infer<typeof ZDocumentLiteSchema>;
/**
* A version of the document response schema when returning multiple documents at once from a single API endpoint.
*/
export const ZDocumentManySchema = DocumentSchema.pick({
export const ZDocumentManySchema = LegacyDocumentSchema.pick({
visibility: true,
status: true,
source: true,
@ -120,16 +142,25 @@ export const ZDocumentManySchema = DocumentSchema.pick({
authOptions: true,
formValues: true,
title: true,
documentDataId: true,
createdAt: true,
updatedAt: true,
completedAt: true,
deletedAt: true,
teamId: true,
templateId: true,
folderId: true,
useLegacyFieldInsertion: true,
}).extend({
envelopeId: z.string(),
// Backwards compatibility.
documentDataId: z.string().default(''),
// Which "Template" the document was created from.
templateId: z
.number()
.nullish()
.describe('The ID of the template that the document was created from, if any.'),
user: UserSchema.pick({
id: true,
name: true,

View File

@ -0,0 +1,138 @@
import { z } from 'zod';
import DocumentDataSchema from '@documenso/prisma/generated/zod/modelSchema/DocumentDataSchema';
import { DocumentMetaSchema } from '@documenso/prisma/generated/zod/modelSchema/DocumentMetaSchema';
import { EnvelopeItemSchema } from '@documenso/prisma/generated/zod/modelSchema/EnvelopeItemSchema';
import { EnvelopeSchema } from '@documenso/prisma/generated/zod/modelSchema/EnvelopeSchema';
import { TeamSchema } from '@documenso/prisma/generated/zod/modelSchema/TeamSchema';
import TemplateDirectLinkSchema from '@documenso/prisma/generated/zod/modelSchema/TemplateDirectLinkSchema';
import { ZFieldSchema } from './field';
import { ZRecipientLiteSchema } from './recipient';
/**
* The full envelope response schema.
*
* Mainly used for returning a single envelope from the API.
*/
export const ZEnvelopeSchema = EnvelopeSchema.pick({
internalVersion: true,
type: true,
status: true,
source: true,
visibility: true,
templateType: true,
id: true,
secondaryId: true,
externalId: true,
createdAt: true,
updatedAt: true,
completedAt: true,
deletedAt: true,
title: true,
authOptions: true,
formValues: true,
publicTitle: true,
publicDescription: true,
userId: true,
teamId: true,
folderId: true,
}).extend({
templateId: z
.number()
.nullish()
.describe('The ID of the template that the document was created from, if any.'),
documentMeta: DocumentMetaSchema.pick({
signingOrder: true,
distributionMethod: true,
id: true,
subject: true,
message: true,
timezone: true,
dateFormat: true,
redirectUrl: true,
typedSignatureEnabled: true,
uploadSignatureEnabled: true,
drawSignatureEnabled: true,
allowDictateNextSigner: true,
language: true,
emailSettings: true,
emailId: true,
emailReplyTo: true,
}),
recipients: ZRecipientLiteSchema.omit({
documentId: true,
templateId: true,
}).array(),
fields: ZFieldSchema.omit({
documentId: true,
templateId: true,
}).array(),
envelopeItems: EnvelopeItemSchema.pick({
id: true,
title: true,
documentDataId: true,
order: true,
})
.extend({
documentData: DocumentDataSchema.pick({
type: true,
id: true,
data: true,
initialData: true, // Todo: Envelopes - Maybe this hide this.
}),
})
.array(),
directLink: TemplateDirectLinkSchema.pick({
directTemplateRecipientId: true,
enabled: true,
id: true,
token: true,
}).nullable(),
team: TeamSchema.pick({
id: true,
url: true,
}),
user: z.object({
id: z.number(),
name: z.string(),
email: z.string(),
}),
});
export type TEnvelope = z.infer<typeof ZEnvelopeSchema>;
/**
* A lite version of the envelope response schema without relations.
*/
export const ZEnvelopeLiteSchema = EnvelopeSchema.pick({
internalVersion: true,
type: true,
status: true,
source: true,
visibility: true,
templateType: true,
id: true,
secondaryId: true,
externalId: true,
createdAt: true,
updatedAt: true,
completedAt: true,
deletedAt: true,
title: true,
authOptions: true,
formValues: true,
publicTitle: true,
publicDescription: true,
userId: true,
teamId: true,
folderId: true,
});
export type TEnvelopeLite = z.infer<typeof ZEnvelopeLiteSchema>;
/**
* A version of the envelope response schema when returning multiple envelopes at once from a single API endpoint.
*/
// export const ZEnvelopeManySchema = X
// export type TEnvelopeMany = z.infer<typeof ZEnvelopeManySchema>;

View File

@ -1,6 +1,8 @@
import { FieldType } from '@prisma/client';
import { z } from 'zod';
export const DEFAULT_FIELD_FONT_SIZE = 14;
export const ZBaseFieldMeta = z.object({
label: z.string().optional(),
placeholder: z.string().optional(),
@ -58,10 +60,10 @@ export type TTextFieldMeta = z.infer<typeof ZTextFieldMeta>;
export const ZNumberFieldMeta = ZBaseFieldMeta.extend({
type: z.literal('number'),
numberFormat: z.string().optional(),
numberFormat: z.string().nullish(),
value: z.string().optional(),
minValue: z.number().optional(),
maxValue: z.number().optional(),
minValue: z.coerce.number().nullish(),
maxValue: z.coerce.number().nullish(),
fontSize: z.number().min(8).max(96).optional(),
textAlign: ZFieldTextAlignSchema.optional(),
});
@ -226,3 +228,86 @@ export const ZFieldAndMetaSchema = z.discriminatedUnion('type', [
]);
export type TFieldAndMeta = z.infer<typeof ZFieldAndMetaSchema>;
export const FIELD_DATE_META_DEFAULT_VALUES: TDateFieldMeta = {
type: 'date',
fontSize: 14,
textAlign: 'left',
};
export const FIELD_TEXT_META_DEFAULT_VALUES: TTextFieldMeta = {
type: 'text',
fontSize: 14,
textAlign: 'left',
label: '',
placeholder: '',
text: '',
required: false,
readOnly: false,
};
export const FIELD_NUMBER_META_DEFAULT_VALUES: TNumberFieldMeta = {
type: 'number',
fontSize: 14,
textAlign: 'left',
label: '',
placeholder: '',
required: false,
readOnly: false,
};
export const FIELD_INITIALS_META_DEFAULT_VALUES: TInitialsFieldMeta = {
type: 'initials',
fontSize: 14,
textAlign: 'left',
};
export const FIELD_NAME_META_DEFAULT_VALUES: TNameFieldMeta = {
type: 'name',
fontSize: 14,
textAlign: 'left',
};
export const FIELD_EMAIL_META_DEFAULT_VALUES: TEmailFieldMeta = {
type: 'email',
fontSize: 14,
textAlign: 'left',
};
export const FIELD_RADIO_META_DEFAULT_VALUES: TRadioFieldMeta = {
type: 'radio',
values: [{ id: 1, checked: false, value: '' }],
required: false,
readOnly: false,
};
export const FIELD_CHECKBOX_META_DEFAULT_VALUES: TCheckboxFieldMeta = {
type: 'checkbox',
values: [{ id: 1, checked: false, value: '' }],
validationRule: '',
validationLength: 0,
required: false,
readOnly: false,
direction: 'vertical',
};
export const FIELD_DROPDOWN_META_DEFAULT_VALUES: TDropdownFieldMeta = {
type: 'dropdown',
values: [{ value: 'Option 1' }],
defaultValue: '',
required: false,
readOnly: false,
};
export const FIELD_META_DEFAULT_VALUES: Record<FieldType, TFieldMetaSchema> = {
[FieldType.SIGNATURE]: undefined,
[FieldType.FREE_SIGNATURE]: undefined,
[FieldType.INITIALS]: FIELD_INITIALS_META_DEFAULT_VALUES,
[FieldType.NAME]: FIELD_NAME_META_DEFAULT_VALUES,
[FieldType.EMAIL]: FIELD_EMAIL_META_DEFAULT_VALUES,
[FieldType.DATE]: FIELD_DATE_META_DEFAULT_VALUES,
[FieldType.TEXT]: FIELD_TEXT_META_DEFAULT_VALUES,
[FieldType.NUMBER]: FIELD_NUMBER_META_DEFAULT_VALUES,
[FieldType.RADIO]: FIELD_RADIO_META_DEFAULT_VALUES,
[FieldType.CHECKBOX]: FIELD_CHECKBOX_META_DEFAULT_VALUES,
[FieldType.DROPDOWN]: FIELD_DROPDOWN_META_DEFAULT_VALUES,
} as const;

View File

@ -1,7 +1,20 @@
import { FieldType, Prisma } from '@prisma/client';
import { z } from 'zod';
import { FieldSchema } from '@documenso/prisma/generated/zod/modelSchema/FieldSchema';
import {
ZCheckboxFieldMeta,
ZDateFieldMeta,
ZDropdownFieldMeta,
ZEmailFieldMeta,
ZInitialsFieldMeta,
ZNameFieldMeta,
ZNumberFieldMeta,
ZRadioFieldMeta,
ZTextFieldMeta,
} from './field-meta';
/**
* The full field response schema.
*
@ -15,11 +28,11 @@ import { FieldSchema } from '@documenso/prisma/generated/zod/modelSchema/FieldSc
* - ./templates.ts
*/
export const ZFieldSchema = FieldSchema.pick({
envelopeId: true,
envelopeItemId: true,
type: true,
id: true,
secondaryId: true,
documentId: true,
templateId: true,
recipientId: true,
page: true,
positionX: true,
@ -29,6 +42,10 @@ export const ZFieldSchema = FieldSchema.pick({
customText: true,
inserted: true,
fieldMeta: true,
}).extend({
// Backwards compatibility.
documentId: z.number().nullish(),
templateId: z.number().nullish(),
});
export const ZFieldPageNumberSchema = z
@ -49,3 +66,110 @@ export const ZFieldPageYSchema = z
export const ZFieldWidthSchema = z.number().min(1).describe('The width of the field.');
export const ZFieldHeightSchema = z.number().min(1).describe('The height of the field.');
// ---------------------------------------------
// Todo: Envelopes - dunno man
const PrismaDecimalSchema = z.preprocess(
(val) => (typeof val === 'string' ? new Prisma.Decimal(val) : val),
z.instanceof(Prisma.Decimal, { message: 'Must be a Decimal' }),
);
export const BaseFieldSchemaUsingNumbers = ZFieldSchema.extend({
positionX: PrismaDecimalSchema,
positionY: PrismaDecimalSchema,
width: PrismaDecimalSchema,
height: PrismaDecimalSchema,
});
export const ZFieldTextSchema = BaseFieldSchemaUsingNumbers.extend({
type: z.literal(FieldType.TEXT),
fieldMeta: ZTextFieldMeta,
});
export type TFieldText = z.infer<typeof ZFieldTextSchema>;
export const ZFieldSignatureSchema = BaseFieldSchemaUsingNumbers.extend({
type: z.literal(FieldType.SIGNATURE),
fieldMeta: z.literal(null),
});
export type TFieldSignature = z.infer<typeof ZFieldSignatureSchema>;
export const ZFieldFreeSignatureSchema = ZFieldSignatureSchema;
export type TFieldFreeSignature = z.infer<typeof ZFieldFreeSignatureSchema>;
export const ZFieldInitialsSchema = BaseFieldSchemaUsingNumbers.extend({
type: z.literal(FieldType.INITIALS),
fieldMeta: ZInitialsFieldMeta,
});
export type TFieldInitials = z.infer<typeof ZFieldInitialsSchema>;
export const ZFieldNameSchema = BaseFieldSchemaUsingNumbers.extend({
type: z.literal(FieldType.NAME),
fieldMeta: ZNameFieldMeta,
});
export type TFieldName = z.infer<typeof ZFieldNameSchema>;
export const ZFieldEmailSchema = BaseFieldSchemaUsingNumbers.extend({
type: z.literal(FieldType.EMAIL),
fieldMeta: ZEmailFieldMeta,
});
export type TFieldEmail = z.infer<typeof ZFieldEmailSchema>;
export const ZFieldDateSchema = BaseFieldSchemaUsingNumbers.extend({
type: z.literal(FieldType.DATE),
fieldMeta: ZDateFieldMeta,
});
export type TFieldDate = z.infer<typeof ZFieldDateSchema>;
export const ZFieldNumberSchema = BaseFieldSchemaUsingNumbers.extend({
type: z.literal(FieldType.NUMBER),
fieldMeta: ZNumberFieldMeta,
});
export type TFieldNumber = z.infer<typeof ZFieldNumberSchema>;
export const ZFieldRadioSchema = BaseFieldSchemaUsingNumbers.extend({
type: z.literal(FieldType.RADIO),
fieldMeta: ZRadioFieldMeta,
});
export type TFieldRadio = z.infer<typeof ZFieldRadioSchema>;
export const ZFieldCheckboxSchema = BaseFieldSchemaUsingNumbers.extend({
type: z.literal(FieldType.CHECKBOX),
fieldMeta: ZCheckboxFieldMeta,
});
export type TFieldCheckbox = z.infer<typeof ZFieldCheckboxSchema>;
export const ZFieldDropdownSchema = BaseFieldSchemaUsingNumbers.extend({
type: z.literal(FieldType.DROPDOWN),
fieldMeta: ZDropdownFieldMeta,
});
export type TFieldDropdown = z.infer<typeof ZFieldDropdownSchema>;
/**
* The full field schema which will enforce all types and meta fields.
*/
export const ZFullFieldSchema = z.discriminatedUnion('type', [
ZFieldTextSchema,
ZFieldSignatureSchema,
ZFieldInitialsSchema,
ZFieldNameSchema,
ZFieldEmailSchema,
ZFieldDateSchema,
ZFieldNumberSchema,
ZFieldRadioSchema,
ZFieldCheckboxSchema,
ZFieldDropdownSchema,
]);
export type TFullFieldSchema = z.infer<typeof ZFullFieldSchema>;

View File

@ -1,3 +1,5 @@
import { z } from 'zod';
import { RecipientSchema } from '@documenso/prisma/generated/zod/modelSchema/RecipientSchema';
import { TeamSchema } from '@documenso/prisma/generated/zod/modelSchema/TeamSchema';
import { UserSchema } from '@documenso/prisma/generated/zod/modelSchema/UserSchema';
@ -10,13 +12,12 @@ import { ZFieldSchema } from './field';
* Mainly used for returning a single recipient from the API.
*/
export const ZRecipientSchema = RecipientSchema.pick({
envelopeId: true,
role: true,
readStatus: true,
signingStatus: true,
sendStatus: true,
id: true,
documentId: true,
templateId: true,
email: true,
name: true,
token: true,
@ -28,19 +29,22 @@ export const ZRecipientSchema = RecipientSchema.pick({
rejectionReason: true,
}).extend({
fields: ZFieldSchema.array(),
// Backwards compatibility.
documentId: z.number().nullish(),
templateId: z.number().nullish(),
});
/**
* A lite version of the recipient response schema without relations.
*/
export const ZRecipientLiteSchema = RecipientSchema.pick({
envelopeId: true,
role: true,
readStatus: true,
signingStatus: true,
sendStatus: true,
id: true,
documentId: true,
templateId: true,
email: true,
name: true,
token: true,
@ -50,19 +54,22 @@ export const ZRecipientLiteSchema = RecipientSchema.pick({
authOptions: true,
signingOrder: true,
rejectionReason: true,
}).extend({
// Backwards compatibility.
documentId: z.number().nullish(),
templateId: z.number().nullish(),
});
/**
* A version of the recipient response schema when returning multiple recipients at once from a single API endpoint.
*/
export const ZRecipientManySchema = RecipientSchema.pick({
envelopeId: true,
role: true,
readStatus: true,
signingStatus: true,
sendStatus: true,
id: true,
documentId: true,
templateId: true,
email: true,
name: true,
token: true,
@ -83,4 +90,8 @@ export const ZRecipientManySchema = RecipientSchema.pick({
id: true,
url: true,
}).nullable(),
// Backwards compatibility.
documentId: z.number().nullish(),
templateId: z.number().nullish(),
});

View File

@ -1,12 +1,14 @@
import type { z } from 'zod';
import { z } from 'zod';
import { DocumentDataSchema } from '@documenso/prisma/generated/zod/modelSchema/DocumentDataSchema';
import { DocumentMetaSchema } from '@documenso/prisma/generated/zod/modelSchema/DocumentMetaSchema';
import { FolderSchema } from '@documenso/prisma/generated/zod/modelSchema/FolderSchema';
import TeamSchema from '@documenso/prisma/generated/zod/modelSchema/TeamSchema';
import { TemplateDirectLinkSchema } from '@documenso/prisma/generated/zod/modelSchema/TemplateDirectLinkSchema';
import { TemplateMetaSchema } from '@documenso/prisma/generated/zod/modelSchema/TemplateMetaSchema';
import { TemplateSchema } from '@documenso/prisma/generated/zod/modelSchema/TemplateSchema';
import { UserSchema } from '@documenso/prisma/generated/zod/modelSchema/UserSchema';
import {
LegacyTemplateDirectLinkSchema,
TemplateSchema,
} from '@documenso/prisma/types/template-legacy-schema';
import { ZFieldSchema } from './field';
import { ZRecipientLiteSchema } from './recipient';
@ -25,21 +27,27 @@ export const ZTemplateSchema = TemplateSchema.pick({
userId: true,
teamId: true,
authOptions: true,
templateDocumentDataId: true,
createdAt: true,
updatedAt: true,
publicTitle: true,
publicDescription: true,
folderId: true,
}).extend({
envelopeId: z.string(),
// Backwards compatibility.
templateDocumentDataId: z.string().default(''),
// Todo: Maybe we want to alter this a bit since this returns a lot of data.
templateDocumentData: DocumentDataSchema.pick({
type: true,
id: true,
data: true,
initialData: true,
}).extend({
envelopeItemId: z.string(),
}),
templateMeta: TemplateMetaSchema.pick({
templateMeta: DocumentMetaSchema.pick({
id: true,
subject: true,
message: true,
@ -51,14 +59,15 @@ export const ZTemplateSchema = TemplateSchema.pick({
drawSignatureEnabled: true,
allowDictateNextSigner: true,
distributionMethod: true,
templateId: true,
redirectUrl: true,
language: true,
emailSettings: true,
emailId: true,
emailReplyTo: true,
}).nullable(),
directLink: TemplateDirectLinkSchema.nullable(),
}).extend({
templateId: z.number().nullable(),
}),
directLink: LegacyTemplateDirectLinkSchema.nullable(),
user: UserSchema.pick({
id: true,
name: true,
@ -94,15 +103,21 @@ export const ZTemplateLiteSchema = TemplateSchema.pick({
userId: true,
teamId: true,
authOptions: true,
templateDocumentDataId: true,
createdAt: true,
updatedAt: true,
publicTitle: true,
publicDescription: true,
folderId: true,
useLegacyFieldInsertion: true,
}).extend({
envelopeId: z.string(),
// Backwards compatibility.
templateDocumentDataId: z.string().default(''),
});
export type TTemplateLite = z.infer<typeof ZTemplateLiteSchema>;
/**
* A version of the template response schema when returning multiple template at once from a single API endpoint.
*/
@ -115,7 +130,6 @@ export const ZTemplateManySchema = TemplateSchema.pick({
userId: true,
teamId: true,
authOptions: true,
templateDocumentDataId: true,
createdAt: true,
updatedAt: true,
publicTitle: true,
@ -123,18 +137,23 @@ export const ZTemplateManySchema = TemplateSchema.pick({
folderId: true,
useLegacyFieldInsertion: true,
}).extend({
envelopeId: z.string(),
team: TeamSchema.pick({
id: true,
url: true,
}).nullable(),
fields: ZFieldSchema.array(),
recipients: ZRecipientLiteSchema.array(),
templateMeta: TemplateMetaSchema.pick({
templateMeta: DocumentMetaSchema.pick({
signingOrder: true,
distributionMethod: true,
}).nullable(),
directLink: TemplateDirectLinkSchema.pick({
directLink: LegacyTemplateDirectLinkSchema.pick({
token: true,
enabled: true,
}).nullable(),
// Backwards compatibility.
templateDocumentDataId: z.string().default(''),
});
export type TTemplateMany = z.infer<typeof ZTemplateManySchema>;

View File

@ -1,10 +1,11 @@
import type { Document, DocumentMeta, Recipient, WebhookTriggerEvents } from '@prisma/client';
import type { DocumentMeta, Envelope, Recipient, WebhookTriggerEvents } from '@prisma/client';
import {
DocumentDistributionMethod,
DocumentSigningOrder,
DocumentSource,
DocumentStatus,
DocumentVisibility,
EnvelopeType,
ReadStatus,
RecipientRole,
SendStatus,
@ -12,6 +13,8 @@ import {
} from '@prisma/client';
import { z } from 'zod';
import { mapSecondaryIdToDocumentId, mapSecondaryIdToTemplateId } from '../utils/envelope';
/**
* Schema for recipient data in webhook payloads.
*/
@ -42,7 +45,6 @@ export const ZWebhookDocumentMetaSchema = z.object({
subject: z.string().nullable(),
message: z.string().nullable(),
timezone: z.string(),
password: z.string().nullable(),
dateFormat: z.string(),
redirectUrl: z.string().nullable(),
signingOrder: z.nativeEnum(DocumentSigningOrder),
@ -67,7 +69,6 @@ export const ZWebhookDocumentSchema = z.object({
visibility: z.nativeEnum(DocumentVisibility),
title: z.string(),
status: z.nativeEnum(DocumentStatus),
documentDataId: z.string(),
createdAt: z.date(),
updatedAt: z.date(),
completedAt: z.date().nullable(),
@ -94,16 +95,54 @@ export type WebhookPayload = {
webhookEndpoint: string;
};
export const mapDocumentToWebhookDocumentPayload = (
document: Document & {
export const mapEnvelopeToWebhookDocumentPayload = (
envelope: Envelope & {
recipients: Recipient[];
documentMeta: DocumentMeta | null;
},
): TWebhookDocument => {
const { recipients, documentMeta, ...trimmedDocument } = document;
const { recipients: rawRecipients, documentMeta } = envelope;
const legacyId =
envelope.type === EnvelopeType.DOCUMENT
? mapSecondaryIdToDocumentId(envelope.secondaryId)
: mapSecondaryIdToTemplateId(envelope.secondaryId);
const mappedRecipients = rawRecipients.map((recipient) => ({
id: recipient.id,
documentId: envelope.type === EnvelopeType.DOCUMENT ? legacyId : null,
templateId: envelope.type === EnvelopeType.TEMPLATE ? legacyId : null,
email: recipient.email,
name: recipient.name,
token: recipient.token,
documentDeletedAt: recipient.documentDeletedAt,
expired: recipient.expired,
signedAt: recipient.signedAt,
authOptions: recipient.authOptions,
signingOrder: recipient.signingOrder,
rejectionReason: recipient.rejectionReason,
role: recipient.role,
readStatus: recipient.readStatus,
signingStatus: recipient.signingStatus,
sendStatus: recipient.sendStatus,
}));
return {
...trimmedDocument,
id: legacyId,
externalId: envelope.externalId,
userId: envelope.userId,
authOptions: envelope.authOptions,
formValues: envelope.formValues,
visibility: envelope.visibility,
title: envelope.title,
status: envelope.status,
createdAt: envelope.createdAt,
updatedAt: envelope.updatedAt,
completedAt: envelope.completedAt,
deletedAt: envelope.deletedAt,
teamId: envelope.teamId,
templateId: envelope.templateId,
source: envelope.source,
documentMeta: documentMeta
? {
...documentMeta,
@ -112,7 +151,7 @@ export const mapDocumentToWebhookDocumentPayload = (
dateFormat: 'yyyy-MM-dd hh:mm a',
}
: null,
Recipient: recipients,
recipients,
Recipient: mappedRecipients,
recipients: mappedRecipients,
};
};