From 0eef4cd7e63c67ac3424f03e6caee83be65184ac Mon Sep 17 00:00:00 2001 From: David Nguyen Date: Tue, 14 Oct 2025 15:19:09 +1100 Subject: [PATCH] fix: additional backwards compat --- .../get-document-with-details-by-id.ts | 13 +++- .../server-only/envelope/create-envelope.ts | 73 +++++++++---------- .../get-envelope-for-recipient-signing.ts | 11 ++- .../field/create-envelope-fields.ts | 3 +- .../lib/server-only/field/get-field-by-id.ts | 3 +- .../field/set-fields-for-document.ts | 5 +- .../field/set-fields-for-template.ts | 5 +- .../field/update-document-fields.ts | 3 +- .../field/update-template-fields.ts | 3 +- .../recipient/create-document-recipients.ts | 5 +- .../recipient/create-template-recipients.ts | 5 +- .../recipient/get-recipient-by-id.ts | 19 ++--- .../recipient/set-document-recipients.ts | 8 +- .../recipient/set-template-recipients.ts | 8 +- .../recipient/update-document-recipients.ts | 10 ++- .../recipient/update-template-recipients.ts | 9 ++- .../get-template-by-direct-link-token.ts | 10 ++- .../template/get-template-by-id.ts | 12 ++- packages/lib/types/document.ts | 15 +++- packages/lib/types/template.ts | 10 +++ packages/lib/universal/id.ts | 17 +++++ packages/lib/utils/document.ts | 7 +- packages/lib/utils/fields.ts | 16 +++- packages/lib/utils/recipients.ts | 14 ++++ packages/lib/utils/templates.ts | 1 + .../create-document-temporary.ts | 22 +++++- .../create-embedding-document.ts | 11 ++- .../get-multi-sign-document.ts | 8 +- .../envelope-router/create-envelope.types.ts | 36 ++++++--- .../set-envelope-recipients.types.ts | 5 +- .../sign-envelope-field.types.ts | 5 +- .../trpc/server/template-router/router.ts | 8 +- 32 files changed, 288 insertions(+), 92 deletions(-) diff --git a/packages/lib/server-only/document/get-document-with-details-by-id.ts b/packages/lib/server-only/document/get-document-with-details-by-id.ts index 7f0cc570a..6612ced39 100644 --- a/packages/lib/server-only/document/get-document-with-details-by-id.ts +++ b/packages/lib/server-only/document/get-document-with-details-by-id.ts @@ -40,6 +40,7 @@ export const getDocumentWithDetailsById = async ({ fields: envelope.fields.map((field) => ({ ...field, documentId: legacyDocumentId, + templateId: null, })), user: { id: envelope.userId, @@ -50,6 +51,16 @@ export const getDocumentWithDetailsById = async ({ id: envelope.teamId, url: envelope.team.url, }, - recipients: envelope.recipients, + recipients: envelope.recipients.map((recipient) => ({ + ...recipient, + documentId: legacyDocumentId, + templateId: null, + })), + documentDataId: firstDocumentData.id, + documentMeta: { + ...envelope.documentMeta, + documentId: legacyDocumentId, + password: null, + }, }; }; diff --git a/packages/lib/server-only/envelope/create-envelope.ts b/packages/lib/server-only/envelope/create-envelope.ts index 0a245fade..606bb05b6 100644 --- a/packages/lib/server-only/envelope/create-envelope.ts +++ b/packages/lib/server-only/envelope/create-envelope.ts @@ -265,6 +265,8 @@ export const createEnvelope = async ({ }, }); + const firstEnvelopeItem = envelope.envelopeItems[0]; + await Promise.all( (data.recipients || []).map(async (recipient) => { const recipientAuthOptions = createRecipientAuthOptions({ @@ -272,44 +274,37 @@ export const createEnvelope = async ({ actionAuth: recipient.actionAuth ?? [], }); - // Todo: Envelopes - Allow fields. - // const recipientFieldsToCreate = (recipient.fields || []).map((field) => { - // let envelopeItemId = envelope.envelopeItems[0].id;? + const recipientFieldsToCreate = (recipient.fields || []).map((field) => { + let envelopeItemId = firstEnvelopeItem.id; - // const foundEnvelopeItem = envelope.envelopeItems.find( - // (item) => item.documentDataId === field.documentDataId, - // ); + if (field.documentDataId) { + const foundEnvelopeItem = envelope.envelopeItems.find( + (item) => item.documentDataId === field.documentDataId, + ); - // if (field.documentDataId && !foundEnvelopeItem) { - // throw new AppError(AppErrorCode.INVALID_REQUEST, { - // message: 'Envelope item not found', - // }); - // } + if (!foundEnvelopeItem) { + throw new AppError(AppErrorCode.NOT_FOUND, { + message: 'Document data not found', + }); + } - // if (foundEnvelopeItem) { - // envelopeItemId = foundEnvelopeItem.id; - // } + envelopeItemId = foundEnvelopeItem.id; + } - // if (!envelopeItemId) { - // throw new AppError(AppErrorCode.INVALID_REQUEST, { - // message: 'Envelope item not found', - // }); - // } - - // return { - // envelopeId: envelope.id, - // envelopeItemId, - // type: field.type, - // page: field.page, - // positionX: field.positionX, - // positionY: field.positionY, - // width: field.width, - // height: field.height, - // customText: '', - // inserted: false, - // fieldMeta: field.fieldMeta || undefined, - // }; - // }); + return { + envelopeId: envelope.id, + envelopeItemId, + type: field.type, + page: field.page, + positionX: field.positionX, + positionY: field.positionY, + width: field.width, + height: field.height, + customText: '', + inserted: false, + fieldMeta: field.fieldMeta || undefined, + }; + }); await tx.recipient.create({ data: { @@ -323,11 +318,11 @@ export const createEnvelope = async ({ signingStatus: recipient.role === RecipientRole.CC ? SigningStatus.SIGNED : SigningStatus.NOT_SIGNED, authOptions: recipientAuthOptions, - // fields: { - // createMany: { - // data: recipientFieldsToCreate, - // }, - // }, + fields: { + createMany: { + data: recipientFieldsToCreate, + }, + }, }, }); }), diff --git a/packages/lib/server-only/envelope/get-envelope-for-recipient-signing.ts b/packages/lib/server-only/envelope/get-envelope-for-recipient-signing.ts index a4999b5ce..e0490cf33 100644 --- a/packages/lib/server-only/envelope/get-envelope-for-recipient-signing.ts +++ b/packages/lib/server-only/envelope/get-envelope-for-recipient-signing.ts @@ -116,9 +116,14 @@ const ZEnvelopeForSigningResponse = z.object({ signingOrder: true, rejectionReason: true, }).extend({ - fields: ZFieldSchema.extend({ - signature: SignatureSchema.nullish(), - }).array(), + fields: ZFieldSchema.omit({ + documentId: true, + templateId: true, + }) + .extend({ + signature: SignatureSchema.nullish(), + }) + .array(), }), recipientSignature: SignatureSchema.pick({ signatureImageAsBase64: true, diff --git a/packages/lib/server-only/field/create-envelope-fields.ts b/packages/lib/server-only/field/create-envelope-fields.ts index ff987b56e..32a41b89f 100644 --- a/packages/lib/server-only/field/create-envelope-fields.ts +++ b/packages/lib/server-only/field/create-envelope-fields.ts @@ -8,6 +8,7 @@ import { prisma } from '@documenso/prisma'; import { AppError, AppErrorCode } from '../../errors/app-error'; import type { EnvelopeIdOptions } from '../../utils/envelope'; +import { mapFieldToLegacyField } from '../../utils/fields'; import { canRecipientFieldsBeModified } from '../../utils/recipients'; import { getEnvelopeWhereInput } from '../envelope/get-envelope-by-id'; @@ -162,6 +163,6 @@ export const createEnvelopeFields = async ({ }); return { - fields: createdFields, + fields: createdFields.map((field) => mapFieldToLegacyField(field, envelope)), }; }; diff --git a/packages/lib/server-only/field/get-field-by-id.ts b/packages/lib/server-only/field/get-field-by-id.ts index 7432a0723..dee488ff6 100644 --- a/packages/lib/server-only/field/get-field-by-id.ts +++ b/packages/lib/server-only/field/get-field-by-id.ts @@ -3,6 +3,7 @@ import type { EnvelopeType } from '@prisma/client'; import { prisma } from '@documenso/prisma'; import { AppError, AppErrorCode } from '../../errors/app-error'; +import { mapFieldToLegacyField } from '../../utils/fields'; import { buildTeamWhereQuery } from '../../utils/teams'; import { getEnvelopeWhereInput } from '../envelope/get-envelope-by-id'; @@ -56,5 +57,5 @@ export const getFieldById = async ({ }); } - return field; + return mapFieldToLegacyField(field, envelope); }; diff --git a/packages/lib/server-only/field/set-fields-for-document.ts b/packages/lib/server-only/field/set-fields-for-document.ts index 8a4c410e9..f564da4a0 100644 --- a/packages/lib/server-only/field/set-fields-for-document.ts +++ b/packages/lib/server-only/field/set-fields-for-document.ts @@ -25,6 +25,7 @@ import { prisma } from '@documenso/prisma'; import { AppError, AppErrorCode } from '../../errors/app-error'; import type { EnvelopeIdOptions } from '../../utils/envelope'; +import { mapFieldToLegacyField } from '../../utils/fields'; import { canRecipientFieldsBeModified } from '../../utils/recipients'; import { getEnvelopeWhereInput } from '../envelope/get-envelope-by-id'; @@ -345,7 +346,9 @@ export const setFieldsForDocument = async ({ }); return { - fields: [...filteredFields, ...persistedFields], + fields: [...filteredFields, ...persistedFields].map((field) => + mapFieldToLegacyField(field, envelope), + ), }; }; diff --git a/packages/lib/server-only/field/set-fields-for-template.ts b/packages/lib/server-only/field/set-fields-for-template.ts index f8ddcfd84..c919c1016 100644 --- a/packages/lib/server-only/field/set-fields-for-template.ts +++ b/packages/lib/server-only/field/set-fields-for-template.ts @@ -18,6 +18,7 @@ import { prisma } from '@documenso/prisma'; import { AppError, AppErrorCode } from '../../errors/app-error'; import type { EnvelopeIdOptions } from '../../utils/envelope'; +import { mapFieldToLegacyField } from '../../utils/fields'; import { getEnvelopeWhereInput } from '../envelope/get-envelope-by-id'; export type SetFieldsForTemplateOptions = { @@ -240,6 +241,8 @@ export const setFieldsForTemplate = async ({ }); return { - fields: [...filteredFields, ...persistedFields], + fields: [...filteredFields, ...persistedFields].map((field) => + mapFieldToLegacyField(field, envelope), + ), }; }; diff --git a/packages/lib/server-only/field/update-document-fields.ts b/packages/lib/server-only/field/update-document-fields.ts index 1237b0284..2df65d436 100644 --- a/packages/lib/server-only/field/update-document-fields.ts +++ b/packages/lib/server-only/field/update-document-fields.ts @@ -10,6 +10,7 @@ import { import { prisma } from '@documenso/prisma'; import { AppError, AppErrorCode } from '../../errors/app-error'; +import { mapFieldToLegacyField } from '../../utils/fields'; import { canRecipientFieldsBeModified } from '../../utils/recipients'; import { getEnvelopeWhereInput } from '../envelope/get-envelope-by-id'; @@ -146,6 +147,6 @@ export const updateDocumentFields = async ({ }); return { - fields: updatedFields, + fields: updatedFields.map((field) => mapFieldToLegacyField(field, envelope)), }; }; diff --git a/packages/lib/server-only/field/update-template-fields.ts b/packages/lib/server-only/field/update-template-fields.ts index 78a8df020..cd05ebbd7 100644 --- a/packages/lib/server-only/field/update-template-fields.ts +++ b/packages/lib/server-only/field/update-template-fields.ts @@ -4,6 +4,7 @@ import type { TFieldMetaSchema } from '@documenso/lib/types/field-meta'; import { prisma } from '@documenso/prisma'; import { AppError, AppErrorCode } from '../../errors/app-error'; +import { mapFieldToLegacyField } from '../../utils/fields'; import { canRecipientFieldsBeModified } from '../../utils/recipients'; import { getEnvelopeWhereInput } from '../envelope/get-envelope-by-id'; @@ -110,6 +111,6 @@ export const updateTemplateFields = async ({ }); return { - fields: updatedFields, + fields: updatedFields.map((field) => mapFieldToLegacyField(field, envelope)), }; }; diff --git a/packages/lib/server-only/recipient/create-document-recipients.ts b/packages/lib/server-only/recipient/create-document-recipients.ts index 7505adfd7..d2b2e0d13 100644 --- a/packages/lib/server-only/recipient/create-document-recipients.ts +++ b/packages/lib/server-only/recipient/create-document-recipients.ts @@ -12,6 +12,7 @@ import { prisma } from '@documenso/prisma'; import { AppError, AppErrorCode } from '../../errors/app-error'; import type { EnvelopeIdOptions } from '../../utils/envelope'; +import { mapRecipientToLegacyRecipient } from '../../utils/recipients'; import { getEnvelopeWhereInput } from '../envelope/get-envelope-by-id'; export interface CreateDocumentRecipientsOptions { @@ -133,6 +134,8 @@ export const createDocumentRecipients = async ({ }); return { - recipients: createdRecipients, + recipients: createdRecipients.map((recipient) => + mapRecipientToLegacyRecipient(recipient, envelope), + ), }; }; diff --git a/packages/lib/server-only/recipient/create-template-recipients.ts b/packages/lib/server-only/recipient/create-template-recipients.ts index 52a954dec..e64e00cfe 100644 --- a/packages/lib/server-only/recipient/create-template-recipients.ts +++ b/packages/lib/server-only/recipient/create-template-recipients.ts @@ -8,6 +8,7 @@ import { createRecipientAuthOptions } from '@documenso/lib/utils/document-auth'; import { prisma } from '@documenso/prisma'; import { AppError, AppErrorCode } from '../../errors/app-error'; +import { mapRecipientToLegacyRecipient } from '../../utils/recipients'; import { getEnvelopeWhereInput } from '../envelope/get-envelope-by-id'; export interface CreateTemplateRecipientsOptions { @@ -107,6 +108,8 @@ export const createTemplateRecipients = async ({ }); return { - recipients: createdRecipients, + recipients: createdRecipients.map((recipient) => + mapRecipientToLegacyRecipient(recipient, template), + ), }; }; diff --git a/packages/lib/server-only/recipient/get-recipient-by-id.ts b/packages/lib/server-only/recipient/get-recipient-by-id.ts index c1162cf50..57a5d9b5b 100644 --- a/packages/lib/server-only/recipient/get-recipient-by-id.ts +++ b/packages/lib/server-only/recipient/get-recipient-by-id.ts @@ -1,5 +1,4 @@ import { EnvelopeType } from '@prisma/client'; -import { match } from 'ts-pattern'; import { prisma } from '@documenso/prisma'; @@ -48,14 +47,16 @@ export const getRecipientById = async ({ }); } - const legacyId = match(type) - .with(EnvelopeType.DOCUMENT, () => ({ - documentId: mapSecondaryIdToDocumentId(recipient.envelope.secondaryId), - })) - .with(EnvelopeType.TEMPLATE, () => ({ - templateId: mapSecondaryIdToTemplateId(recipient.envelope.secondaryId), - })) - .exhaustive(); + const legacyId = { + documentId: + type === EnvelopeType.DOCUMENT + ? mapSecondaryIdToDocumentId(recipient.envelope.secondaryId) + : null, + templateId: + type === EnvelopeType.TEMPLATE + ? mapSecondaryIdToTemplateId(recipient.envelope.secondaryId) + : null, + }; // Backwards compatibility mapping. return { diff --git a/packages/lib/server-only/recipient/set-document-recipients.ts b/packages/lib/server-only/recipient/set-document-recipients.ts index 3ace7a5e5..6d185ded4 100644 --- a/packages/lib/server-only/recipient/set-document-recipients.ts +++ b/packages/lib/server-only/recipient/set-document-recipients.ts @@ -27,7 +27,7 @@ import { getI18nInstance } from '../../client-only/providers/i18n-server'; import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app'; import { AppError, AppErrorCode } from '../../errors/app-error'; import { extractDerivedDocumentEmailSettings } from '../../types/document-email'; -import type { EnvelopeIdOptions } from '../../utils/envelope'; +import { type EnvelopeIdOptions, mapSecondaryIdToDocumentId } from '../../utils/envelope'; import { canRecipientBeModified } from '../../utils/recipients'; import { renderEmailWithI18N } from '../../utils/render-email-with-i18n'; import { getEmailContext } from '../email/get-email-context'; @@ -344,7 +344,11 @@ export const setDocumentRecipients = async ({ }); return { - recipients: [...filteredRecipients, ...persistedRecipients], + recipients: [...filteredRecipients, ...persistedRecipients].map((recipient) => ({ + ...recipient, + documentId: mapSecondaryIdToDocumentId(envelope.secondaryId), + templateId: null, + })), }; }; diff --git a/packages/lib/server-only/recipient/set-template-recipients.ts b/packages/lib/server-only/recipient/set-template-recipients.ts index 3d0f411b9..1743968c1 100644 --- a/packages/lib/server-only/recipient/set-template-recipients.ts +++ b/packages/lib/server-only/recipient/set-template-recipients.ts @@ -14,7 +14,7 @@ import { } from '../../types/document-auth'; import { nanoid } from '../../universal/id'; import { createRecipientAuthOptions } from '../../utils/document-auth'; -import type { EnvelopeIdOptions } from '../../utils/envelope'; +import { type EnvelopeIdOptions, mapSecondaryIdToTemplateId } from '../../utils/envelope'; import { getEnvelopeWhereInput } from '../envelope/get-envelope-by-id'; export type SetTemplateRecipientsOptions = { @@ -211,6 +211,10 @@ export const setTemplateRecipients = async ({ }); return { - recipients: [...filteredRecipients, ...persistedRecipients], + recipients: [...filteredRecipients, ...persistedRecipients].map((recipient) => ({ + ...recipient, + documentId: null, + templateId: mapSecondaryIdToTemplateId(envelope.secondaryId), + })), }; }; diff --git a/packages/lib/server-only/recipient/update-document-recipients.ts b/packages/lib/server-only/recipient/update-document-recipients.ts index c451599b9..bede48dfe 100644 --- a/packages/lib/server-only/recipient/update-document-recipients.ts +++ b/packages/lib/server-only/recipient/update-document-recipients.ts @@ -16,7 +16,8 @@ import { createRecipientAuthOptions } from '@documenso/lib/utils/document-auth'; import { prisma } from '@documenso/prisma'; import { AppError, AppErrorCode } from '../../errors/app-error'; -import type { EnvelopeIdOptions } from '../../utils/envelope'; +import { type EnvelopeIdOptions, mapSecondaryIdToDocumentId } from '../../utils/envelope'; +import { mapFieldToLegacyField } from '../../utils/fields'; import { canRecipientBeModified } from '../../utils/recipients'; import { getEnvelopeWhereInput } from '../envelope/get-envelope-by-id'; @@ -185,7 +186,12 @@ export const updateDocumentRecipients = async ({ }); return { - recipients: updatedRecipients, + recipients: updatedRecipients.map((recipient) => ({ + ...recipient, + documentId: mapSecondaryIdToDocumentId(envelope.secondaryId), + templateId: null, + fields: recipient.fields.map((field) => mapFieldToLegacyField(field, envelope)), + })), }; }; diff --git a/packages/lib/server-only/recipient/update-template-recipients.ts b/packages/lib/server-only/recipient/update-template-recipients.ts index 208853e47..45bdff76b 100644 --- a/packages/lib/server-only/recipient/update-template-recipients.ts +++ b/packages/lib/server-only/recipient/update-template-recipients.ts @@ -10,6 +10,8 @@ import { createRecipientAuthOptions } from '@documenso/lib/utils/document-auth'; import { prisma } from '@documenso/prisma'; import { AppError, AppErrorCode } from '../../errors/app-error'; +import { mapSecondaryIdToTemplateId } from '../../utils/envelope'; +import { mapFieldToLegacyField } from '../../utils/fields'; import { getEnvelopeWhereInput } from '../envelope/get-envelope-by-id'; export interface UpdateTemplateRecipientsOptions { @@ -156,6 +158,11 @@ export const updateTemplateRecipients = async ({ }); return { - recipients: updatedRecipients, + recipients: updatedRecipients.map((recipient) => ({ + ...recipient, + documentId: null, + templateId: mapSecondaryIdToTemplateId(envelope.secondaryId), + fields: recipient.fields.map((field) => mapFieldToLegacyField(field, envelope)), + })), }; }; diff --git a/packages/lib/server-only/template/get-template-by-direct-link-token.ts b/packages/lib/server-only/template/get-template-by-direct-link-token.ts index 2c28533b7..486b81f92 100644 --- a/packages/lib/server-only/template/get-template-by-direct-link-token.ts +++ b/packages/lib/server-only/template/get-template-by-direct-link-token.ts @@ -48,10 +48,12 @@ export const getTemplateByDirectLinkToken = async ({ const recipientsWithMappedFields = envelope.recipients.map((recipient) => ({ ...recipient, + templateId: mapSecondaryIdToTemplateId(envelope.secondaryId), + documentId: null, fields: recipient.fields.map((field) => ({ ...field, templateId: mapSecondaryIdToTemplateId(envelope.secondaryId), - documentId: undefined, + documentId: null, })), })); @@ -71,6 +73,7 @@ export const getTemplateByDirectLinkToken = async ({ publicTitle: envelope.publicTitle, publicDescription: envelope.publicDescription, folderId: envelope.folderId, + templateDocumentDataId: firstDocumentData.id, templateDocumentData: { ...firstDocumentData, envelopeItemId: envelope.envelopeItems[0].id, @@ -79,7 +82,10 @@ export const getTemplateByDirectLinkToken = async ({ ...directLink, templateId: mapSecondaryIdToTemplateId(envelope.secondaryId), }, - templateMeta: envelope.documentMeta, + templateMeta: { + ...envelope.documentMeta, + templateId: mapSecondaryIdToTemplateId(envelope.secondaryId), + }, recipients: recipientsWithMappedFields, fields: recipientsWithMappedFields.flatMap((recipient) => recipient.fields), }; diff --git a/packages/lib/server-only/template/get-template-by-id.ts b/packages/lib/server-only/template/get-template-by-id.ts index f231f315f..546e16e39 100644 --- a/packages/lib/server-only/template/get-template-by-id.ts +++ b/packages/lib/server-only/template/get-template-by-id.ts @@ -68,13 +68,23 @@ export const getTemplateById = async ({ id, userId, teamId }: GetTemplateByIdOpt ...rest, envelopeId: envelope.id, type: envelope.templateType, + templateDocumentDataId: firstTemplateDocumentData.id, templateDocumentData: { ...firstTemplateDocumentData, envelopeItemId: envelope.envelopeItems[0].id, }, - templateMeta: envelope.documentMeta, + templateMeta: { + ...envelope.documentMeta, + templateId: legacyTemplateId, + }, fields: envelope.fields.map((field) => ({ ...field, + documentId: null, + templateId: legacyTemplateId, + })), + recipients: envelope.recipients.map((recipient) => ({ + ...recipient, + documentId: null, templateId: legacyTemplateId, })), directLink: envelope.directLink diff --git a/packages/lib/types/document.ts b/packages/lib/types/document.ts index 923072f13..ea69f7db8 100644 --- a/packages/lib/types/document.ts +++ b/packages/lib/types/document.ts @@ -40,6 +40,9 @@ export const ZDocumentSchema = LegacyDocumentSchema.pick({ .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, @@ -66,7 +69,11 @@ export const ZDocumentSchema = LegacyDocumentSchema.pick({ emailSettings: true, emailId: true, emailReplyTo: true, - }).nullable(), + }).extend({ + password: z.string().nullable().default(null), + documentId: z.number().default(-1).optional(), + }), + folder: FolderSchema.pick({ id: true, name: true, @@ -108,6 +115,9 @@ export const ZDocumentLiteSchema = LegacyDocumentSchema.pick({ }).extend({ envelopeId: z.string(), + // Backwards compatibility. + documentDataId: z.string().default(''), + // Which "Template" the document was created from. templateId: z .number() @@ -140,6 +150,9 @@ export const ZDocumentManySchema = LegacyDocumentSchema.pick({ }).extend({ envelopeId: z.string(), + // Backwards compatibility. + documentDataId: z.string().default(''), + // Which "Template" the document was created from. templateId: z .number() diff --git a/packages/lib/types/template.ts b/packages/lib/types/template.ts index 30207c4d7..0ba6b0010 100644 --- a/packages/lib/types/template.ts +++ b/packages/lib/types/template.ts @@ -35,6 +35,9 @@ export const ZTemplateSchema = TemplateSchema.pick({ }).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, @@ -61,6 +64,8 @@ export const ZTemplateSchema = TemplateSchema.pick({ emailSettings: true, emailId: true, emailReplyTo: true, + }).extend({ + templateId: z.number().nullable(), }), directLink: LegacyTemplateDirectLinkSchema.nullable(), user: UserSchema.pick({ @@ -106,6 +111,9 @@ export const ZTemplateLiteSchema = TemplateSchema.pick({ useLegacyFieldInsertion: true, }).extend({ envelopeId: z.string(), + + // Backwards compatibility. + templateDocumentDataId: z.string().default(''), }); export type TTemplateLite = z.infer; @@ -144,6 +152,8 @@ export const ZTemplateManySchema = TemplateSchema.pick({ token: true, enabled: true, }).nullable(), + // Backwards compatibility. + templateDocumentDataId: z.string().default(''), }); export type TTemplateMany = z.infer; diff --git a/packages/lib/universal/id.ts b/packages/lib/universal/id.ts index 1c34200b3..e681becf1 100644 --- a/packages/lib/universal/id.ts +++ b/packages/lib/universal/id.ts @@ -1,5 +1,9 @@ +import type { Envelope } from '@prisma/client'; +import { EnvelopeType } from '@prisma/client'; import { customAlphabet } from 'nanoid'; +import { mapSecondaryIdToDocumentId, mapSecondaryIdToTemplateId } from '../utils/envelope'; + export const alphaid = customAlphabet('0123456789abcdefghijklmnopqrstuvwxyz', 21); export { nanoid } from 'nanoid'; @@ -29,3 +33,16 @@ type DatabaseIdPrefix = | 'team_setting'; export const generateDatabaseId = (prefix: DatabaseIdPrefix) => prefixedId(prefix, 16); + +export const extractLegacyIds = (envelope: Pick) => { + return { + documentId: + envelope.type === EnvelopeType.DOCUMENT + ? mapSecondaryIdToDocumentId(envelope.secondaryId) + : null, + templateId: + envelope.type === EnvelopeType.TEMPLATE + ? mapSecondaryIdToTemplateId(envelope.secondaryId) + : null, + }; +}; diff --git a/packages/lib/utils/document.ts b/packages/lib/utils/document.ts index a13bd27cb..8fb4d24e8 100644 --- a/packages/lib/utils/document.ts +++ b/packages/lib/utils/document.ts @@ -12,6 +12,7 @@ import { DEFAULT_DOCUMENT_TIME_ZONE } from '../constants/time-zones'; import type { TDocumentLite, TDocumentMany } from '../types/document'; import { DEFAULT_DOCUMENT_EMAIL_SETTINGS } from '../types/document-email'; import { mapSecondaryIdToDocumentId } from './envelope'; +import { mapRecipientToLegacyRecipient } from './recipients'; export const isDocumentCompleted = (document: Pick | DocumentStatus) => { const status = typeof document === 'string' ? document : document.status; @@ -84,6 +85,7 @@ export const mapEnvelopeToDocumentLite = (envelope: Envelope): TDocumentLite => formValues: envelope.formValues, title: envelope.title, createdAt: envelope.createdAt, + documentDataId: '', // Backwards compatibility. updatedAt: envelope.updatedAt, completedAt: envelope.completedAt, deletedAt: envelope.deletedAt, @@ -122,6 +124,7 @@ export const mapEnvelopesToDocumentMany = ( formValues: envelope.formValues, title: envelope.title, createdAt: envelope.createdAt, + documentDataId: '', // Backwards compatibility. updatedAt: envelope.updatedAt, completedAt: envelope.completedAt, deletedAt: envelope.deletedAt, @@ -138,6 +141,8 @@ export const mapEnvelopesToDocumentMany = ( id: envelope.teamId, url: envelope.team.url, }, - recipients: envelope.recipients, + recipients: envelope.recipients.map((recipient) => + mapRecipientToLegacyRecipient(recipient, envelope), + ), }; }; diff --git a/packages/lib/utils/fields.ts b/packages/lib/utils/fields.ts index c1646c3bf..be7c23e07 100644 --- a/packages/lib/utils/fields.ts +++ b/packages/lib/utils/fields.ts @@ -1,4 +1,6 @@ -import type { Field } from '@prisma/client'; +import { type Envelope, type Field } from '@prisma/client'; + +import { extractLegacyIds } from '../universal/id'; /** * Sort the fields by the Y position on the document. @@ -63,3 +65,15 @@ export const validateFieldsUninserted = (): boolean => { return errorElements.length === 0; }; + +export const mapFieldToLegacyField = ( + field: Field, + envelope: Pick, +) => { + const legacyId = extractLegacyIds(envelope); + + return { + ...field, + ...legacyId, + }; +}; diff --git a/packages/lib/utils/recipients.ts b/packages/lib/utils/recipients.ts index dc973cdb1..70411ad4d 100644 --- a/packages/lib/utils/recipients.ts +++ b/packages/lib/utils/recipients.ts @@ -1,6 +1,8 @@ +import type { Envelope } from '@prisma/client'; import { type Field, type Recipient, RecipientRole, SigningStatus } from '@prisma/client'; import { NEXT_PUBLIC_WEBAPP_URL } from '../constants/app'; +import { extractLegacyIds } from '../universal/id'; export const formatSigningLink = (token: string) => `${NEXT_PUBLIC_WEBAPP_URL()}/sign/${token}`; @@ -44,3 +46,15 @@ export const canRecipientFieldsBeModified = (recipient: Recipient, fields: Field return recipient.role !== RecipientRole.VIEWER && recipient.role !== RecipientRole.CC; }; + +export const mapRecipientToLegacyRecipient = ( + recipient: Recipient, + envelope: Pick, +) => { + const legacyId = extractLegacyIds(envelope); + + return { + ...recipient, + ...legacyId, + }; +}; diff --git a/packages/lib/utils/templates.ts b/packages/lib/utils/templates.ts index d02b2839f..5e22474e2 100644 --- a/packages/lib/utils/templates.ts +++ b/packages/lib/utils/templates.ts @@ -65,5 +65,6 @@ export const mapEnvelopeToTemplateLite = (envelope: Envelope): TTemplateLite => publicDescription: envelope.publicDescription, folderId: envelope.folderId, useLegacyFieldInsertion: envelope.useLegacyFieldInsertion, + templateDocumentDataId: '', }; }; diff --git a/packages/trpc/server/document-router/create-document-temporary.ts b/packages/trpc/server/document-router/create-document-temporary.ts index 1473fcad0..219b7f286 100644 --- a/packages/trpc/server/document-router/create-document-temporary.ts +++ b/packages/trpc/server/document-router/create-document-temporary.ts @@ -69,7 +69,16 @@ export const createDocumentTemporaryRoute = authenticatedProcedure visibility, globalAccessAuth, globalActionAuth, - recipients, + recipients: (recipients || []).map((recipient) => ({ + ...recipient, + fields: (recipient.fields || []).map((field) => ({ + ...field, + page: field.pageNumber, + positionX: field.pageX, + positionY: field.pageY, + documentDataId: documentData.id, + })), + })), folderId, envelopeItems: [ { @@ -102,14 +111,25 @@ export const createDocumentTemporaryRoute = authenticatedProcedure document: { ...createdEnvelope, envelopeId: createdEnvelope.id, + documentDataId: firstDocumentData.id, documentData: { ...firstDocumentData, envelopeItemId: envelopeItems[0].id, }, + documentMeta: { + ...createdEnvelope.documentMeta, + documentId: legacyDocumentId, + }, id: legacyDocumentId, fields: createdEnvelope.fields.map((field) => ({ ...field, documentId: legacyDocumentId, + templateId: null, + })), + recipients: createdEnvelope.recipients.map((recipient) => ({ + ...recipient, + documentId: legacyDocumentId, + templateId: null, })), }, folder: createdEnvelope.folder, // Todo: Remove this prior to api-v2 release. diff --git a/packages/trpc/server/embedding-router/create-embedding-document.ts b/packages/trpc/server/embedding-router/create-embedding-document.ts index 3a8db92dc..d1155e456 100644 --- a/packages/trpc/server/embedding-router/create-embedding-document.ts +++ b/packages/trpc/server/embedding-router/create-embedding-document.ts @@ -39,7 +39,16 @@ export const createEmbeddingDocumentRoute = procedure type: EnvelopeType.DOCUMENT, title, externalId, - recipients, + recipients: (recipients || []).map((recipient) => ({ + ...recipient, + fields: (recipient.fields || []).map((field) => ({ + ...field, + page: field.pageNumber, + positionX: field.pageX, + positionY: field.pageY, + documentDataId, + })), + })), envelopeItems: [ { documentDataId, diff --git a/packages/trpc/server/embedding-router/get-multi-sign-document.ts b/packages/trpc/server/embedding-router/get-multi-sign-document.ts index 60a6813c0..c05b73f89 100644 --- a/packages/trpc/server/embedding-router/get-multi-sign-document.ts +++ b/packages/trpc/server/embedding-router/get-multi-sign-document.ts @@ -42,7 +42,13 @@ export const getMultiSignDocumentRoute = procedure // Transform fields to match our schema const transformedFields = fields.map((field) => ({ ...field, - recipient, + recipient: { + ...recipient, + documentId: document.id, + templateId: null, + }, + documentId: document.id, + templateId: null, })); return { diff --git a/packages/trpc/server/envelope-router/create-envelope.types.ts b/packages/trpc/server/envelope-router/create-envelope.types.ts index bebb19ccc..5f1e04cbf 100644 --- a/packages/trpc/server/envelope-router/create-envelope.types.ts +++ b/packages/trpc/server/envelope-router/create-envelope.types.ts @@ -7,6 +7,14 @@ import { } from '@documenso/lib/types/document-auth'; import { ZDocumentFormValuesSchema } from '@documenso/lib/types/document-form-values'; import { ZDocumentMetaCreateSchema } from '@documenso/lib/types/document-meta'; +import { + ZFieldHeightSchema, + ZFieldPageNumberSchema, + ZFieldPageXSchema, + ZFieldPageYSchema, + ZFieldWidthSchema, +} from '@documenso/lib/types/field'; +import { ZFieldAndMetaSchema } from '@documenso/lib/types/field-meta'; import { ZDocumentExternalIdSchema, @@ -48,18 +56,22 @@ export const ZCreateEnvelopeRequestSchema = z.object({ recipients: z .array( ZCreateRecipientSchema.extend({ - // Todo: Envelopes ? - // fields: ZFieldAndMetaSchema.and( - // z.object({ - // pageNumber: ZFieldPageNumberSchema, - // pageX: ZFieldPageXSchema, - // pageY: ZFieldPageYSchema, - // width: ZFieldWidthSchema, - // height: ZFieldHeightSchema, - // }), - // ) - // .array() - // .optional(), + fields: ZFieldAndMetaSchema.and( + z.object({ + documentDataId: z + .string() + .describe( + 'The ID of the document data to create the field on. If empty, the first document data will be used.', + ), + page: ZFieldPageNumberSchema, + positionX: ZFieldPageXSchema, + positionY: ZFieldPageYSchema, + width: ZFieldWidthSchema, + height: ZFieldHeightSchema, + }), + ) + .array() + .optional(), }), ) .optional(), diff --git a/packages/trpc/server/envelope-router/set-envelope-recipients.types.ts b/packages/trpc/server/envelope-router/set-envelope-recipients.types.ts index 0af815c0b..c24fd6402 100644 --- a/packages/trpc/server/envelope-router/set-envelope-recipients.types.ts +++ b/packages/trpc/server/envelope-router/set-envelope-recipients.types.ts @@ -20,7 +20,10 @@ export const ZSetEnvelopeRecipientsRequestSchema = z.object({ }); export const ZSetEnvelopeRecipientsResponseSchema = z.object({ - recipients: ZRecipientLiteSchema.array(), + recipients: ZRecipientLiteSchema.omit({ + documentId: true, + templateId: true, + }).array(), }); export type TSetEnvelopeRecipientsRequest = z.infer; diff --git a/packages/trpc/server/envelope-router/sign-envelope-field.types.ts b/packages/trpc/server/envelope-router/sign-envelope-field.types.ts index 84f3115cf..4ac138808 100644 --- a/packages/trpc/server/envelope-router/sign-envelope-field.types.ts +++ b/packages/trpc/server/envelope-router/sign-envelope-field.types.ts @@ -57,7 +57,10 @@ export const ZSignEnvelopeFieldRequestSchema = z.object({ }); export const ZSignEnvelopeFieldResponseSchema = z.object({ - signedField: ZFieldSchema.extend({ + signedField: ZFieldSchema.omit({ + templateId: true, + documentId: true, + }).extend({ signature: SignatureSchema.nullish(), }), }); diff --git a/packages/trpc/server/template-router/router.ts b/packages/trpc/server/template-router/router.ts index fe89bbf0b..68bbd2127 100644 --- a/packages/trpc/server/template-router/router.ts +++ b/packages/trpc/server/template-router/router.ts @@ -23,6 +23,8 @@ import { getTemplateById } from '@documenso/lib/server-only/template/get-templat import { toggleTemplateDirectLink } from '@documenso/lib/server-only/template/toggle-template-direct-link'; import { getPresignPostUrl } from '@documenso/lib/universal/upload/server-actions'; import { mapSecondaryIdToTemplateId } from '@documenso/lib/utils/envelope'; +import { mapFieldToLegacyField } from '@documenso/lib/utils/fields'; +import { mapRecipientToLegacyRecipient } from '@documenso/lib/utils/recipients'; import { mapEnvelopeToTemplateLite } from '@documenso/lib/utils/templates'; import { ZGenericSuccessResponse, ZSuccessResponseSchema } from '../document-router/schema'; @@ -106,8 +108,10 @@ export const templateRouter = router({ folderId: envelope.folderId, useLegacyFieldInsertion: envelope.useLegacyFieldInsertion, team: envelope.team, - fields: envelope.fields, - recipients: envelope.recipients, + fields: envelope.fields.map((field) => mapFieldToLegacyField(field, envelope)), + recipients: envelope.recipients.map((recipient) => + mapRecipientToLegacyRecipient(recipient, envelope), + ), templateMeta: envelope.documentMeta, directLink: envelope.directLink, };