chore: merge main, resolve biome formatting conflicts

Merge origin/main into feat/external-2fa-codes. Resolve formatting
conflicts caused by biome rollout; preserve both feature streams:
PR's external 2FA token + signing-session 2FA proof additions plus
main's RateLimit/RecipientExpired/signingReminders/date-auto-insert.

In complete-document-with-token.ts, drop the duplicate early
field-fetching block introduced when main moved that logic later
with date auto-insert support; keep the EXTERNAL_TWO_FACTOR_AUTH
check using derivedRecipientActionAuth.
This commit is contained in:
ephraimduncan
2026-05-12 11:46:11 +00:00
parent 9194884fbe
commit 138d663c25
1959 changed files with 93488 additions and 47038 deletions
+49
View File
@@ -0,0 +1,49 @@
import { z } from 'zod';
/**
* A CSS length value: `0`, or a positive number followed by a length unit.
* Used for the radius field, which is interpolated raw into a `<style>`
* block at render time. Anything outside this shape is a CSS-injection
* vector — DO NOT loosen without re-checking `toNativeCssVars`.
*/
export const CSS_LENGTH_REGEX = /^(0|\d+(\.\d+)?(rem|px|em|%|pt|))$/i;
export const ZCssVarsSchema = z
.object({
background: z.string().optional().describe('Base background color'),
foreground: z.string().optional().describe('Base text color'),
muted: z.string().optional().describe('Muted/subtle background color'),
mutedForeground: z.string().optional().describe('Muted/subtle text color'),
popover: z.string().optional().describe('Popover/dropdown background color'),
popoverForeground: z.string().optional().describe('Popover/dropdown text color'),
card: z.string().optional().describe('Card background color'),
cardBorder: z.string().optional().describe('Card border color'),
cardBorderTint: z.string().optional().describe('Card border tint/highlight color'),
cardForeground: z.string().optional().describe('Card text color'),
fieldCard: z.string().optional().describe('Field card background color'),
fieldCardBorder: z.string().optional().describe('Field card border color'),
fieldCardForeground: z.string().optional().describe('Field card text color'),
widget: z.string().optional().describe('Widget background color'),
widgetForeground: z.string().optional().describe('Widget text color'),
border: z.string().optional().describe('Default border color'),
input: z.string().optional().describe('Input field border color'),
primary: z.string().optional().describe('Primary action/button color'),
primaryForeground: z.string().optional().describe('Primary action/button text color'),
secondary: z.string().optional().describe('Secondary action/button color'),
secondaryForeground: z.string().optional().describe('Secondary action/button text color'),
accent: z.string().optional().describe('Accent/highlight color'),
accentForeground: z.string().optional().describe('Accent/highlight text color'),
destructive: z.string().optional().describe('Destructive/danger action color'),
destructiveForeground: z.string().optional().describe('Destructive/danger text color'),
ring: z.string().optional().describe('Focus ring color'),
radius: z
.string()
.regex(CSS_LENGTH_REGEX, 'Must be a CSS length such as 0.5rem, 8px, or 0')
.optional()
.describe('Border radius — must be a CSS length (rem/px/em/%/pt or 0)'),
warning: z.string().optional().describe('Warning/alert color'),
envelopeEditorBackground: z.string().optional().describe('Envelope editor background color'),
})
.describe('Custom CSS variables for theming');
export type TCssVarsSchema = z.infer<typeof ZCssVarsSchema>;
+3 -1
View File
@@ -1,8 +1,10 @@
import { RecipientRole } from '@prisma/client';
import { z } from 'zod';
import { zEmail } from '../utils/zod';
export const ZDefaultRecipientSchema = z.object({
email: z.string().email(),
email: zEmail(),
name: z.string(),
role: z.nativeEnum(RecipientRole),
});
+56 -32
View File
@@ -7,6 +7,7 @@
import { DocumentSource, FieldType } from '@prisma/client';
import { z } from 'zod';
import { zEmail } from '../utils/zod';
import { ZRecipientAccessAuthTypesSchema, ZRecipientActionAuthTypesSchema } from './document-auth';
export const ZDocumentAuditLogTypeSchema = z.enum([
@@ -23,6 +24,8 @@ export const ZDocumentAuditLogTypeSchema = z.enum([
'ENVELOPE_ITEM_CREATED',
'ENVELOPE_ITEM_DELETED',
'ENVELOPE_ITEM_UPDATED',
'ENVELOPE_ITEM_PDF_REPLACED',
// Document events.
'DOCUMENT_COMPLETED', // When the document is sealed and fully completed.
@@ -40,6 +43,7 @@ export const ZDocumentAuditLogTypeSchema = z.enum([
'DOCUMENT_VIEWED', // When the document is viewed by a recipient.
'DOCUMENT_RECIPIENT_REJECTED', // When a recipient rejects the document.
'DOCUMENT_RECIPIENT_COMPLETED', // When a recipient completes all their required tasks for the document.
'DOCUMENT_RECIPIENT_EXPIRED', // When a recipient's signing window expires.
'DOCUMENT_SENT', // When the document transitions from DRAFT to PENDING.
'DOCUMENT_TITLE_UPDATED', // When the document title is updated.
'DOCUMENT_EXTERNAL_ID_UPDATED', // When the document external ID is updated.
@@ -67,6 +71,7 @@ export const ZDocumentAuditLogEmailTypeSchema = z.enum([
'ASSISTING_REQUEST',
'CC',
'DOCUMENT_COMPLETED',
'REMINDER',
]);
export const ZDocumentMetaDiffTypeSchema = z.enum([
@@ -82,13 +87,7 @@ export const ZDocumentMetaDiffTypeSchema = z.enum([
]);
export const ZFieldDiffTypeSchema = z.enum(['DIMENSION', 'POSITION']);
export const ZRecipientDiffTypeSchema = z.enum([
'NAME',
'ROLE',
'EMAIL',
'ACCESS_AUTH',
'ACTION_AUTH',
]);
export const ZRecipientDiffTypeSchema = z.enum(['NAME', 'ROLE', 'EMAIL', 'ACCESS_AUTH', 'ACTION_AUTH']);
export const DOCUMENT_AUDIT_LOG_TYPE = ZDocumentAuditLogTypeSchema.Enum;
export const DOCUMENT_EMAIL_TYPE = ZDocumentAuditLogEmailTypeSchema.Enum;
@@ -142,10 +141,7 @@ export const ZDocumentAuditLogDocumentMetaSchema = z.union([
}),
]);
export const ZDocumentAuditLogFieldDiffSchema = z.union([
ZFieldDiffDimensionSchema,
ZFieldDiffPositionSchema,
]);
export const ZDocumentAuditLogFieldDiffSchema = z.union([ZFieldDiffDimensionSchema, ZFieldDiffPositionSchema]);
export const ZGenericFromToSchema = z.object({
from: z.union([z.string(), z.array(z.string())]).nullable(),
@@ -216,6 +212,34 @@ export const ZDocumentAuditLogEventEnvelopeItemDeletedSchema = z.object({
}),
});
/**
* Event: Envelope item updated.
*/
export const ZDocumentAuditLogEventEnvelopeItemUpdatedSchema = z.object({
type: z.literal(DOCUMENT_AUDIT_LOG_TYPE.ENVELOPE_ITEM_UPDATED),
data: z.object({
envelopeItemId: z.string(),
changes: z.array(
z.object({
field: z.string(),
from: z.string(),
to: z.string(),
}),
),
}),
});
/**
* Event: Envelope item PDF replaced.
*/
export const ZDocumentAuditLogEventEnvelopeItemPdfReplacedSchema = z.object({
type: z.literal(DOCUMENT_AUDIT_LOG_TYPE.ENVELOPE_ITEM_PDF_REPLACED),
data: z.object({
envelopeItemId: z.string(),
envelopeItemTitle: z.string(),
}),
});
/**
* Event: Email sent.
*/
@@ -256,7 +280,7 @@ export const ZDocumentAuditLogEventDocumentCreatedSchema = z.object({
z.object({
type: z.literal(DocumentSource.TEMPLATE_DIRECT_LINK),
templateId: z.number(),
directRecipientEmail: z.string().email(),
directRecipientEmail: zEmail(),
}),
])
.optional(),
@@ -331,11 +355,7 @@ export const ZDocumentAuditLogEventDocumentFieldInsertedSchema = z.object({
});
// Replace legacy 'NONE' field security type with undefined.
if (
typeof input === 'object' &&
input !== null &&
JSON.stringify(input) === legacyNoneSecurityType
) {
if (typeof input === 'object' && input !== null && JSON.stringify(input) === legacyNoneSecurityType) {
return undefined;
}
@@ -435,11 +455,7 @@ export const ZDocumentAuditLogEventDocumentFieldPrefilledSchema = z.object({
});
// Replace legacy 'NONE' field security type with undefined.
if (
typeof input === 'object' &&
input !== null &&
JSON.stringify(input) === legacyNoneSecurityType
) {
if (typeof input === 'object' && input !== null && JSON.stringify(input) === legacyNoneSecurityType) {
return undefined;
}
@@ -755,6 +771,18 @@ export const ZDocumentAuditLogEventExternal2FATokenRevokedSchema = z.object({
}),
});
/**
* Event: Recipient's signing window expired.
*/
export const ZDocumentAuditLogEventRecipientExpiredSchema = z.object({
type: z.literal(DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_EXPIRED),
data: z.object({
recipientEmail: z.string(),
recipientName: z.string(),
recipientId: z.number(),
}),
});
export const ZDocumentAuditLogBaseSchema = z.object({
id: z.string(),
createdAt: z.date(),
@@ -770,6 +798,8 @@ export const ZDocumentAuditLogSchema = ZDocumentAuditLogBaseSchema.and(
z.union([
ZDocumentAuditLogEventEnvelopeItemCreatedSchema,
ZDocumentAuditLogEventEnvelopeItemDeletedSchema,
ZDocumentAuditLogEventEnvelopeItemUpdatedSchema,
ZDocumentAuditLogEventEnvelopeItemPdfReplacedSchema,
ZDocumentAuditLogEventEmailSentSchema,
ZDocumentAuditLogEventDocumentCompletedSchema,
ZDocumentAuditLogEventDocumentCreatedSchema,
@@ -806,6 +836,7 @@ export const ZDocumentAuditLogSchema = ZDocumentAuditLogBaseSchema.and(
ZDocumentAuditLogEventExternal2FATokenVerifyFailedSchema,
ZDocumentAuditLogEventExternal2FATokenConsumedSchema,
ZDocumentAuditLogEventExternal2FATokenRevokedSchema,
ZDocumentAuditLogEventRecipientExpiredSchema,
]),
);
@@ -814,17 +845,10 @@ export type TDocumentAuditLogType = z.infer<typeof ZDocumentAuditLogTypeSchema>;
export type TDocumentAuditLogFieldDiffSchema = z.infer<typeof ZDocumentAuditLogFieldDiffSchema>;
export type TDocumentAuditLogDocumentMetaDiffSchema = z.infer<
typeof ZDocumentAuditLogDocumentMetaSchema
>;
export type TDocumentAuditLogDocumentMetaDiffSchema = z.infer<typeof ZDocumentAuditLogDocumentMetaSchema>;
export type TDocumentAuditLogRecipientDiffSchema = z.infer<
typeof ZDocumentAuditLogRecipientDiffSchema
>;
export type TDocumentAuditLogRecipientDiffSchema = z.infer<typeof ZDocumentAuditLogRecipientDiffSchema>;
export type DocumentAuditLogByType<T = TDocumentAuditLog['type']> = Extract<
TDocumentAuditLog,
{ type: T }
>;
export type DocumentAuditLogByType<T = TDocumentAuditLog['type']> = Extract<TDocumentAuditLog, { type: T }>;
export type TDocumentAuditLogBaseSchema = z.infer<typeof ZDocumentAuditLogBaseSchema>;
+4 -8
View File
@@ -148,10 +148,8 @@ export const ZDocumentAuthOptionsSchema = z.preprocess(
};
}
const globalAccessAuth =
'globalAccessAuth' in unknownValue ? processAuthValue(unknownValue.globalAccessAuth) : [];
const globalActionAuth =
'globalActionAuth' in unknownValue ? processAuthValue(unknownValue.globalActionAuth) : [];
const globalAccessAuth = 'globalAccessAuth' in unknownValue ? processAuthValue(unknownValue.globalAccessAuth) : [];
const globalActionAuth = 'globalActionAuth' in unknownValue ? processAuthValue(unknownValue.globalActionAuth) : [];
return {
globalAccessAuth,
@@ -176,10 +174,8 @@ export const ZRecipientAuthOptionsSchema = z.preprocess(
};
}
const accessAuth =
'accessAuth' in unknownValue ? processAuthValue(unknownValue.accessAuth) : [];
const actionAuth =
'actionAuth' in unknownValue ? processAuthValue(unknownValue.actionAuth) : [];
const accessAuth = 'accessAuth' in unknownValue ? processAuthValue(unknownValue.accessAuth) : [];
const actionAuth = 'actionAuth' in unknownValue ? processAuthValue(unknownValue.actionAuth) : [];
return {
accessAuth,
+20 -19
View File
@@ -10,27 +10,23 @@ export enum DocumentEmailEvents {
DocumentCompleted = 'documentCompleted',
DocumentDeleted = 'documentDeleted',
OwnerDocumentCompleted = 'ownerDocumentCompleted',
OwnerRecipientExpired = 'ownerRecipientExpired',
OwnerDocumentCreated = 'ownerDocumentCreated',
}
export const ZDocumentEmailSettingsSchema = z
.object({
recipientSigningRequest: z
.boolean()
.describe(
'Whether to send an email to all recipients that the document is ready for them to sign.',
)
.describe('Whether to send an email to all recipients that the document is ready for them to sign.')
.default(true),
recipientRemoved: z
.boolean()
.describe(
'Whether to send an email to the recipient who was removed from a pending document.',
)
.describe('Whether to send an email to the recipient who was removed from a pending document.')
.default(true),
recipientSigned: z
.boolean()
.describe(
'Whether to send an email to the document owner when a recipient has signed the document.',
)
.describe('Whether to send an email to the document owner when a recipient has signed the document.')
.default(true),
documentPending: z
.boolean()
@@ -44,29 +40,30 @@ export const ZDocumentEmailSettingsSchema = z
.default(true),
documentDeleted: z
.boolean()
.describe(
'Whether to send an email to all recipients if a pending document has been deleted.',
)
.describe('Whether to send an email to all recipients if a pending document has been deleted.')
.default(true),
ownerDocumentCompleted: z
.boolean()
.describe('Whether to send an email to the document owner when the document is complete.')
.default(true),
ownerRecipientExpired: z
.boolean()
.describe("Whether to send an email to the document owner when a recipient's signing window has expired.")
.default(true),
ownerDocumentCreated: z
.boolean()
.describe('Whether to send an email to the document owner when a document is created from a direct template.')
.default(true),
})
.strip()
.catch(() => ({ ...DEFAULT_DOCUMENT_EMAIL_SETTINGS }));
export type TDocumentEmailSettings = z.infer<typeof ZDocumentEmailSettingsSchema>;
export const extractDerivedDocumentEmailSettings = (
documentMeta?: DocumentMeta | null,
): TDocumentEmailSettings => {
export const extractDerivedDocumentEmailSettings = (documentMeta?: DocumentMeta | null): TDocumentEmailSettings => {
const emailSettings = ZDocumentEmailSettingsSchema.parse(documentMeta?.emailSettings ?? {});
if (
!documentMeta?.distributionMethod ||
documentMeta?.distributionMethod === DocumentDistributionMethod.EMAIL
) {
if (!documentMeta?.distributionMethod || documentMeta?.distributionMethod === DocumentDistributionMethod.EMAIL) {
return emailSettings;
}
@@ -78,6 +75,8 @@ export const extractDerivedDocumentEmailSettings = (
documentCompleted: false,
documentDeleted: false,
ownerDocumentCompleted: emailSettings.ownerDocumentCompleted,
ownerRecipientExpired: emailSettings.ownerRecipientExpired,
ownerDocumentCreated: emailSettings.ownerDocumentCreated,
};
};
@@ -89,4 +88,6 @@ export const DEFAULT_DOCUMENT_EMAIL_SETTINGS: TDocumentEmailSettings = {
documentCompleted: true,
documentDeleted: true,
ownerDocumentCompleted: true,
ownerRecipientExpired: true,
ownerDocumentCreated: true,
};
+1 -4
View File
@@ -1,8 +1,5 @@
import { z } from 'zod';
export const ZDocumentFormValuesSchema = z.record(
z.string(),
z.union([z.string(), z.boolean(), z.number()]),
);
export const ZDocumentFormValuesSchema = z.record(z.string(), z.union([z.string(), z.boolean(), z.number()]));
export type TDocumentFormValues = z.infer<typeof ZDocumentFormValuesSchema>;
+12 -12
View File
@@ -1,12 +1,14 @@
import { VALID_DATE_FORMAT_VALUES } from '@documenso/lib/constants/date-formats';
import { ZEnvelopeExpirationPeriod } from '@documenso/lib/constants/envelope-expiration';
import { ZEnvelopeReminderSettings } from '@documenso/lib/constants/envelope-reminder';
import { SUPPORTED_LANGUAGE_CODES } from '@documenso/lib/constants/i18n';
import { isValidRedirectUrl } from '@documenso/lib/utils/is-valid-redirect-url';
import { zEmail } from '@documenso/lib/utils/zod';
import { DocumentMetaSchema } from '@documenso/prisma/generated/zod/modelSchema/DocumentMetaSchema';
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';
/**
@@ -45,9 +47,7 @@ export const ZDocumentSignatureSettingsSchema = z
})
.refine(
(data) => {
return (
data.typedSignatureEnabled || data.uploadSignatureEnabled || data.drawnSignatureEnabled
);
return data.typedSignatureEnabled || data.uploadSignatureEnabled || data.drawnSignatureEnabled;
},
{
message: msg`At least one signature type must be enabled`.id,
@@ -58,9 +58,7 @@ export type TDocumentSignatureSettings = z.infer<typeof ZDocumentSignatureSettin
export const ZDocumentMetaTimezoneSchema = z
.string()
.describe(
'The timezone to use for date fields and signing the document. Example Etc/UTC, Australia/Melbourne',
);
.describe('The timezone to use for date fields and signing the document. Example Etc/UTC, Australia/Melbourne');
export type TDocumentMetaTimezone = z.infer<typeof ZDocumentMetaTimezoneSchema>;
@@ -126,8 +124,10 @@ export const ZDocumentMetaCreateSchema = z.object({
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
emailId: z.string().nullish(),
emailReplyTo: z.string().email().nullish(),
emailReplyTo: zEmail().nullish(),
emailSettings: ZDocumentEmailSettingsSchema.nullish(),
envelopeExpirationPeriod: ZEnvelopeExpirationPeriod.nullish(),
reminderSettings: ZEnvelopeReminderSettings.nullish(),
});
export type TDocumentMetaCreate = z.infer<typeof ZDocumentMetaCreateSchema>;
+8 -14
View File
@@ -1,5 +1,3 @@
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';
@@ -7,6 +5,7 @@ import { FolderSchema } from '@documenso/prisma/generated/zod/modelSchema/Folder
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 { z } from 'zod';
import { ZFieldSchema } from './field';
import { ZRecipientLiteSchema } from './recipient';
@@ -37,10 +36,7 @@ export const ZDocumentSchema = LegacyDocumentSchema.pick({
internalVersion: z.number(),
// 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.'),
templateId: z.number().nullish().describe('The ID of the template that the document was created from, if any.'),
// Backwards compatibility.
documentDataId: z.string().default(''),
@@ -71,6 +67,8 @@ export const ZDocumentSchema = LegacyDocumentSchema.pick({
emailSettings: true,
emailId: true,
emailReplyTo: true,
envelopeExpirationPeriod: true,
reminderSettings: true,
}).extend({
password: z.string().nullable().default(null),
documentId: z.number().default(-1).optional(),
@@ -126,10 +124,7 @@ export const ZDocumentLiteSchema = LegacyDocumentSchema.pick({
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.'),
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>;
@@ -162,10 +157,7 @@ export const ZDocumentManySchema = LegacyDocumentSchema.pick({
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.'),
templateId: z.number().nullish().describe('The ID of the template that the document was created from, if any.'),
user: UserSchema.pick({
id: true,
@@ -180,3 +172,5 @@ export const ZDocumentManySchema = LegacyDocumentSchema.pick({
});
export type TDocumentMany = z.infer<typeof ZDocumentManySchema>;
export type DocumentDataVersion = 'initial' | 'current';
+3 -2
View File
@@ -1,6 +1,5 @@
import type { z } from 'zod';
import { EmailDomainSchema } from '@documenso/prisma/generated/zod/modelSchema/EmailDomainSchema';
import type { z } from 'zod';
import { ZOrganisationEmailLiteSchema } from './organisation-email';
@@ -18,6 +17,7 @@ export const ZEmailDomainSchema = EmailDomainSchema.pick({
publicKey: true,
createdAt: true,
updatedAt: true,
lastVerifiedAt: true,
}).extend({
emails: ZOrganisationEmailLiteSchema.array(),
});
@@ -35,6 +35,7 @@ export const ZEmailDomainManySchema = EmailDomainSchema.pick({
selector: true,
createdAt: true,
updatedAt: true,
lastVerifiedAt: true,
});
export type TEmailDomainMany = z.infer<typeof ZEmailDomainManySchema>;
@@ -0,0 +1,25 @@
import { z } from 'zod';
import { ZBaseEmbedDataSchema } from './embed-base-schemas';
export const ZBaseEmbedAuthoringSchema = ZBaseEmbedDataSchema.extend({
externalId: z.string().optional(),
features: z
.object({
allowConfigureSignatureTypes: z.boolean().optional(),
allowConfigureLanguage: z.boolean().optional(),
allowConfigureDateFormat: z.boolean().optional(),
allowConfigureTimezone: z.boolean().optional(),
allowConfigureRedirectUrl: z.boolean().optional(),
allowConfigureCommunication: z.boolean().optional(),
})
.optional()
.default({}),
});
export const ZBaseEmbedAuthoringEditSchema = ZBaseEmbedAuthoringSchema.extend({
onlyEditFields: z.boolean().optional().default(false),
});
export type TBaseEmbedAuthoringSchema = z.infer<typeof ZBaseEmbedAuthoringSchema>;
export type TBaseEmbedAuthoringEditSchema = z.infer<typeof ZBaseEmbedAuthoringEditSchema>;
+14
View File
@@ -0,0 +1,14 @@
import { ZSupportedLanguageCodeSchema } from '@documenso/lib/constants/locales';
import { z } from 'zod';
import { ZCssVarsSchema } from './css-vars';
export const ZBaseEmbedDataSchema = z.object({
darkModeDisabled: z.boolean().optional().default(false),
css: z
.string()
.optional()
.transform((value) => value || undefined),
cssVars: ZCssVarsSchema.optional().default({}),
language: ZSupportedLanguageCodeSchema.optional(),
});
@@ -0,0 +1,21 @@
import { z } from 'zod';
import { zEmail } from '../utils/zod';
import { ZBaseEmbedDataSchema } from './embed-base-schemas';
export const ZDirectTemplateEmbedDataSchema = ZBaseEmbedDataSchema.extend({
email: z
.union([z.literal(''), zEmail()])
.optional()
.transform((value) => value || undefined),
lockEmail: z.boolean().optional().default(false),
name: z
.string()
.optional()
.transform((value) => value || undefined),
lockName: z.boolean().optional().default(false),
});
export type TDirectTemplateEmbedDataSchema = z.infer<typeof ZDirectTemplateEmbedDataSchema>;
export type TDirectTemplateEmbedDataInputSchema = z.input<typeof ZDirectTemplateEmbedDataSchema>;
@@ -0,0 +1,19 @@
import { z } from 'zod';
import { zEmail } from '../utils/zod';
import { ZBaseEmbedDataSchema } from './embed-base-schemas';
export const ZSignDocumentEmbedDataSchema = ZBaseEmbedDataSchema.extend({
email: z
.union([z.literal(''), zEmail()])
.optional()
.transform((value) => value || undefined),
lockEmail: z.boolean().optional().default(false),
name: z
.string()
.optional()
.transform((value) => value || undefined),
lockName: z.boolean().optional().default(false),
allowDocumentRejection: z.boolean().optional(),
showOtherRecipientsCompletedFields: z.boolean().optional(),
});
@@ -0,0 +1,18 @@
import { z } from 'zod';
import { zEmail } from '../utils/zod';
import { ZBaseEmbedDataSchema } from './embed-base-schemas';
export const ZEmbedMultiSignDocumentSchema = ZBaseEmbedDataSchema.extend({
email: z
.union([z.literal(''), zEmail()])
.optional()
.transform((value) => value || undefined),
lockEmail: z.boolean().optional().default(false),
name: z
.string()
.optional()
.transform((value) => value || undefined),
lockName: z.boolean().optional().default(false),
allowDocumentRejection: z.boolean().optional(),
});
+342
View File
@@ -0,0 +1,342 @@
import { ZBaseEmbedDataSchema } from '@documenso/lib/types/embed-base-schemas';
import { ZEnvelopeFieldSchema } from '@documenso/lib/types/field';
import { ZEnvelopeRecipientLiteSchema } from '@documenso/lib/types/recipient';
import { DocumentMetaSchema } from '@documenso/prisma/generated/zod/modelSchema/DocumentMetaSchema';
import { EnvelopeAttachmentSchema } from '@documenso/prisma/generated/zod/modelSchema/EnvelopeAttachmentSchema';
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 { EnvelopeType } from '@prisma/client';
import { z } from 'zod';
/**
* DO NOT MAKE ANY BREAKING BACKWARD CHANGES HERE UNLESS YOU'RE SURE
* IT WON'T BREAK EMBEDDINGS.
*
* Keep this in sync with the embedded repo (the types + schema)
*/
export const ZEnvelopeEditorSettingsSchema = z.object({
/**
* Generic editor related configurations.
*/
general: z.object({
allowConfigureEnvelopeTitle: z.boolean(),
allowUploadAndRecipientStep: z.boolean(),
allowAddFieldsStep: z.boolean(),
allowPreviewStep: z.boolean(),
minimizeLeftSidebar: z.boolean(),
}),
/**
* Envelope meta/settings related configuration
*
* If null, the settings will not be available to be seen/updated.
*/
settings: z
.object({
allowConfigureSignatureTypes: z.boolean(),
allowConfigureLanguage: z.boolean(),
allowConfigureDateFormat: z.boolean(),
allowConfigureTimezone: z.boolean(),
allowConfigureRedirectUrl: z.boolean(),
allowConfigureDistribution: z.boolean(),
allowConfigureExpirationPeriod: z.boolean(),
allowConfigureReminders: z.boolean(),
allowConfigureEmailSender: z.boolean(),
allowConfigureEmailReplyTo: z.boolean(),
})
.nullable(),
/**
* Action related configurations.
*/
actions: z.object({
allowAttachments: z.boolean(),
allowDistributing: z.boolean(),
allowDirectLink: z.boolean(),
allowDuplication: z.boolean(),
allowSaveAsTemplate: z.boolean(),
allowDownloadPDF: z.boolean(),
allowDeletion: z.boolean(),
}),
/**
* Envelope items related configurations.
*
* If null, no adjustments to envelope items will be allowed.
*/
envelopeItems: z
.object({
allowConfigureTitle: z.boolean(),
allowConfigureOrder: z.boolean(),
allowUpload: z.boolean(),
allowDelete: z.boolean(),
allowReplace: z.boolean(),
})
.nullable(),
/**
* Recipient related configurations.
*
* If null, recipients will not be configurable at all.
*/
recipients: z
.object({
allowAIDetection: z.boolean(),
allowConfigureSigningOrder: z.boolean(),
allowConfigureDictateNextSigner: z.boolean(),
allowApproverRole: z.boolean(),
allowViewerRole: z.boolean(),
allowCCerRole: z.boolean(),
allowAssistantRole: z.boolean(),
})
.nullable(),
/**
* Fields related configurations.
*/
fields: z.object({
allowAIDetection: z.boolean(),
}),
});
export type TEnvelopeEditorSettings = z.infer<typeof ZEnvelopeEditorSettingsSchema>;
/**
* The default editor configuration for normal flows.
*/
export const DEFAULT_EDITOR_CONFIG: EnvelopeEditorConfig = {
general: {
allowConfigureEnvelopeTitle: true,
allowUploadAndRecipientStep: true,
allowAddFieldsStep: true,
allowPreviewStep: true,
minimizeLeftSidebar: false,
},
settings: {
allowConfigureSignatureTypes: true,
allowConfigureLanguage: true,
allowConfigureDateFormat: true,
allowConfigureTimezone: true,
allowConfigureRedirectUrl: true,
allowConfigureDistribution: true,
allowConfigureExpirationPeriod: true,
allowConfigureReminders: true,
allowConfigureEmailSender: true,
allowConfigureEmailReplyTo: true,
},
actions: {
allowAttachments: true,
allowDistributing: true,
allowDirectLink: true,
allowDuplication: true,
allowSaveAsTemplate: true,
allowDownloadPDF: true,
allowDeletion: true,
},
envelopeItems: {
allowConfigureTitle: true,
allowConfigureOrder: true,
allowUpload: true,
allowDelete: true,
allowReplace: true,
},
recipients: {
allowAIDetection: true,
allowConfigureSigningOrder: true,
allowConfigureDictateNextSigner: true,
allowApproverRole: true,
allowViewerRole: true,
allowCCerRole: true,
allowAssistantRole: true,
},
fields: {
allowAIDetection: true,
},
};
/**
* The default configuration for the embedded editor. This is merged with whatever is provided
* by the embedded hash.
*
* This is duplicated in the embedded repo playground
*
* /playground/src/components/embedddings/envelope-feature.ts
*/
export const DEFAULT_EMBEDDED_EDITOR_CONFIG = {
general: {
allowConfigureEnvelopeTitle: true,
allowUploadAndRecipientStep: true,
allowAddFieldsStep: true,
allowPreviewStep: true,
minimizeLeftSidebar: true,
},
settings: {
allowConfigureSignatureTypes: true,
allowConfigureLanguage: true,
allowConfigureDateFormat: true,
allowConfigureTimezone: true,
allowConfigureRedirectUrl: true,
allowConfigureDistribution: true,
allowConfigureExpirationPeriod: true,
allowConfigureReminders: true,
allowConfigureEmailSender: true,
allowConfigureEmailReplyTo: true,
},
actions: {
allowAttachments: true,
allowDistributing: false, // These are not supported for embeds, and are directly excluded in the embedded repo.
allowDirectLink: false, // These are not supported for embeds, and are directly excluded in the embedded repo.
allowDuplication: false, // These are not supported for embeds, and are directly excluded in the embedded repo.
allowSaveAsTemplate: false, // These are not supported for embeds, and are directly excluded in the embedded repo.
allowDownloadPDF: false, // These are not supported for embeds, and are directly excluded in the embedded repo.
allowDeletion: false, // These are not supported for embeds, and are directly excluded in the embedded repo.
},
envelopeItems: {
allowConfigureTitle: true,
allowConfigureOrder: true,
allowUpload: true,
allowDelete: true,
allowReplace: true,
},
recipients: {
allowAIDetection: false, // These are not supported for embeds, and are directly excluded in the embedded repo.
allowConfigureSigningOrder: true,
allowConfigureDictateNextSigner: true,
allowApproverRole: true,
allowViewerRole: true,
allowCCerRole: true,
allowAssistantRole: true,
},
fields: {
allowAIDetection: false, // These are not supported for embeds, and are directly excluded in the embedded repo.
},
} as const satisfies EnvelopeEditorConfig;
export const ZEmbedCreateEnvelopeAuthoringSchema = ZBaseEmbedDataSchema.extend({
externalId: z.string().optional(),
type: z.nativeEnum(EnvelopeType),
folderId: z.string().optional(),
user: z
.object({
email: z.string().email().optional(),
name: z.string().optional(),
})
.optional(),
features: z.object({}).passthrough().optional().default(DEFAULT_EMBEDDED_EDITOR_CONFIG),
});
export const ZEmbedEditEnvelopeAuthoringSchema = ZBaseEmbedDataSchema.extend({
externalId: z.string().optional(),
user: z
.object({
email: z.string().email().optional(),
name: z.string().optional(),
})
.optional(),
features: z.object({}).passthrough().optional().default(DEFAULT_EMBEDDED_EDITOR_CONFIG),
});
export type TEmbedCreateEnvelopeAuthoring = z.infer<typeof ZEmbedCreateEnvelopeAuthoringSchema>;
export type TEmbedEditEnvelopeAuthoring = z.infer<typeof ZEmbedEditEnvelopeAuthoringSchema>;
/**
* A subset of the full envelope response schema used for the envelope editor.
*
* Internal usage only.
*/
export const ZEditorEnvelopeSchema = EnvelopeSchema.pick({
internalVersion: true,
type: true,
status: true,
source: true,
visibility: true,
templateType: true,
id: true,
secondaryId: true,
externalId: true,
completedAt: true,
deletedAt: true,
title: true,
authOptions: true,
publicTitle: true,
publicDescription: true,
userId: true,
teamId: true,
folderId: true,
}).extend({
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,
envelopeExpirationPeriod: true,
reminderSettings: true,
}),
recipients: ZEnvelopeRecipientLiteSchema.array(),
fields: ZEnvelopeFieldSchema.array(),
envelopeItems: EnvelopeItemSchema.pick({
envelopeId: true,
id: true,
title: true,
order: true,
documentDataId: true,
})
.extend({
// Only used for embedded.
data: z.instanceof(Uint8Array).optional(),
})
.array(),
directLink: TemplateDirectLinkSchema.pick({
directTemplateRecipientId: true,
enabled: true,
id: true,
token: true,
}).nullable(),
team: TeamSchema.pick({
id: true,
url: true,
organisationId: true,
}),
user: z.object({
id: z.number(),
name: z.string(),
email: z.string(),
}),
attachments: EnvelopeAttachmentSchema.pick({
id: true,
type: true,
label: true,
data: true,
}).array(),
});
export type TEditorEnvelope = z.infer<typeof ZEditorEnvelopeSchema>;
export type EnvelopeEditorConfig = TEnvelopeEditorSettings & {
embedded?: {
presignToken: string;
mode: 'create' | 'edit';
onCreate?: (envelope: Omit<TEditorEnvelope, 'id'>) => void;
onUpdate?: (envelope: TEditorEnvelope) => void;
customBrandingLogo?: boolean;
user?: {
email?: string;
name?: string;
};
};
};
+3 -2
View File
@@ -1,10 +1,9 @@
import { z } from 'zod';
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 { z } from 'zod';
import { ZEnvelopeFieldSchema } from './field';
import { ZEnvelopeRecipientLiteSchema } from './recipient';
@@ -55,11 +54,13 @@ export const ZEnvelopeSchema = EnvelopeSchema.pick({
emailSettings: true,
emailId: true,
emailReplyTo: true,
envelopeExpirationPeriod: true,
}),
recipients: ZEnvelopeRecipientLiteSchema.array(),
fields: ZEnvelopeFieldSchema.array(),
envelopeItems: EnvelopeItemSchema.pick({
envelopeId: true,
documentDataId: true,
id: true,
title: true,
order: true,
+36 -8
View File
@@ -16,6 +16,32 @@ export const FIELD_MAX_LETTER_SPACING = 100;
export const DEFAULT_FIELD_FONT_SIZE = 12;
export const DEFAULT_SIGNATURE_OVERFLOW_MODE = 'auto';
export const DEFAULT_DATE_OVERFLOW_MODE = 'auto';
export const DEFAULT_EMAIL_OVERFLOW_MODE = 'auto';
/**
* The overflow mode for a field.
*
* - 'auto': Will overflow horizontally if no room to wrap vertically.
* - 'horizontal': Overflow horizontally, will not wrap at all.
* - 'vertical': Overflow vertically, will wrap at the field width.
* - 'crop': Crop the text to the field bounds, will not overflow at all.
*
* @default 'crop'
*/
export const ZFieldOverflowMode = z.enum(['auto', 'horizontal', 'vertical', 'crop']);
export type TFieldOverflowMode = z.infer<typeof ZFieldOverflowMode>;
/**
* Resolves the overflow mode for a field.
*
* Returns 'crop' when undefined (the default for most fields).
*/
export const resolveFieldOverflowMode = (fieldMeta?: { overflow?: TFieldOverflowMode } | null): TFieldOverflowMode => {
return fieldMeta?.overflow ?? 'crop';
};
/**
* Grouped field types that use the same generic text rendering function.
*/
@@ -37,9 +63,7 @@ const ZFieldMetaLetterSpacing = z.coerce
.min(FIELD_MIN_LETTER_SPACING)
.max(FIELD_MAX_LETTER_SPACING)
.describe('The spacing between each character');
const ZFieldMetaVerticalAlign = z
.enum(['top', 'middle', 'bottom'])
.describe('The vertical alignment of the text');
const ZFieldMetaVerticalAlign = z.enum(['top', 'middle', 'bottom']).describe('The vertical alignment of the text');
export const ZBaseFieldMeta = z.object({
label: z.string().optional(),
@@ -47,6 +71,7 @@ export const ZBaseFieldMeta = z.object({
required: z.boolean().optional(),
readOnly: z.boolean().optional(),
fontSize: z.number().min(8).max(96).default(DEFAULT_FIELD_FONT_SIZE).optional(),
overflow: ZFieldOverflowMode.optional(),
});
export type TBaseFieldMeta = z.infer<typeof ZBaseFieldMeta>;
@@ -72,6 +97,7 @@ export type TNameFieldMeta = z.infer<typeof ZNameFieldMeta>;
export const ZEmailFieldMeta = ZBaseFieldMeta.extend({
type: z.literal('email'),
textAlign: ZFieldTextAlignSchema.optional(),
overflow: ZFieldOverflowMode.optional().default(DEFAULT_EMAIL_OVERFLOW_MODE),
});
export type TEmailFieldMeta = z.infer<typeof ZEmailFieldMeta>;
@@ -79,6 +105,7 @@ export type TEmailFieldMeta = z.infer<typeof ZEmailFieldMeta>;
export const ZDateFieldMeta = ZBaseFieldMeta.extend({
type: z.literal('date'),
textAlign: ZFieldTextAlignSchema.optional(),
overflow: ZFieldOverflowMode.optional().default(DEFAULT_DATE_OVERFLOW_MODE),
});
export type TDateFieldMeta = z.infer<typeof ZDateFieldMeta>;
@@ -86,10 +113,7 @@ export type TDateFieldMeta = z.infer<typeof ZDateFieldMeta>;
export const ZTextFieldMeta = ZBaseFieldMeta.extend({
type: z.literal('text'),
text: z.string().optional(),
characterLimit: z.coerce
.number({ invalid_type_error: 'Value must be a number' })
.min(0)
.optional(),
characterLimit: z.coerce.number({ invalid_type_error: 'Value must be a number' }).min(0).optional(),
textAlign: ZFieldTextAlignSchema.optional(),
lineHeight: ZFieldMetaLineHeight.nullish(),
letterSpacing: ZFieldMetaLetterSpacing.nullish(),
@@ -156,6 +180,7 @@ export type TDropdownFieldMeta = z.infer<typeof ZDropdownFieldMeta>;
export const ZSignatureFieldMeta = ZBaseFieldMeta.extend({
type: z.literal('signature'),
overflow: ZFieldOverflowMode.optional().default(DEFAULT_SIGNATURE_OVERFLOW_MODE),
});
export type TSignatureFieldMeta = z.infer<typeof ZSignatureFieldMeta>;
@@ -283,6 +308,7 @@ export const FIELD_DATE_META_DEFAULT_VALUES: TDateFieldMeta = {
type: 'date',
fontSize: DEFAULT_FIELD_FONT_SIZE,
textAlign: 'left',
overflow: DEFAULT_DATE_OVERFLOW_MODE,
};
export const FIELD_TEXT_META_DEFAULT_VALUES: TTextFieldMeta = {
@@ -322,6 +348,7 @@ export const FIELD_EMAIL_META_DEFAULT_VALUES: TEmailFieldMeta = {
type: 'email',
fontSize: DEFAULT_FIELD_FONT_SIZE,
textAlign: 'left',
overflow: DEFAULT_EMAIL_OVERFLOW_MODE,
};
export const FIELD_RADIO_META_DEFAULT_VALUES: TRadioFieldMeta = {
@@ -356,6 +383,7 @@ export const FIELD_DROPDOWN_META_DEFAULT_VALUES: TDropdownFieldMeta = {
export const FIELD_SIGNATURE_META_DEFAULT_VALUES: TSignatureFieldMeta = {
type: 'signature',
fontSize: DEFAULT_SIGNATURE_TEXT_FONT_SIZE,
overflow: DEFAULT_SIGNATURE_OVERFLOW_MODE,
};
export const FIELD_META_DEFAULT_VALUES: Record<FieldType, TFieldMetaSchema> = {
@@ -419,4 +447,4 @@ export const ZEnvelopeFieldAndMetaSchema = z.discriminatedUnion('type', [
}),
]);
type TEnvelopeFieldAndMeta = z.infer<typeof ZEnvelopeFieldAndMetaSchema>;
export type TEnvelopeFieldAndMeta = z.infer<typeof ZEnvelopeFieldAndMetaSchema>;
+4 -14
View File
@@ -1,8 +1,7 @@
import { FieldSchema } from '@documenso/prisma/generated/zod/modelSchema/FieldSchema';
import { FieldType, Prisma } from '@prisma/client';
import { z } from 'zod';
import { FieldSchema } from '@documenso/prisma/generated/zod/modelSchema/FieldSchema';
import {
FIELD_SIGNATURE_META_DEFAULT_VALUES,
ZCheckboxFieldMeta,
@@ -55,20 +54,11 @@ export const ZEnvelopeFieldSchema = ZFieldSchema.omit({
templateId: true,
});
export const ZFieldPageNumberSchema = z
.number()
.min(1)
.describe('The page number the field will be on.');
export const ZFieldPageNumberSchema = z.number().min(1).describe('The page number the field will be on.');
export const ZFieldPageXSchema = z
.number()
.min(0)
.describe('The X coordinate of where the field will be placed.');
export const ZFieldPageXSchema = z.number().min(0).describe('The X coordinate of where the field will be placed.');
export const ZFieldPageYSchema = z
.number()
.min(0)
.describe('The Y coordinate of where the field will be placed.');
export const ZFieldPageYSchema = z.number().min(0).describe('The Y coordinate of where the field will be placed.');
export const ZFieldWidthSchema = z.number().min(1).describe('The width of the field.');
+1
View File
@@ -8,6 +8,7 @@ export const ZLicenseClaimSchema = z.object({
embedAuthoring: z.boolean().optional(),
embedAuthoringWhiteLabel: z.boolean().optional(),
cfr21: z.boolean().optional(),
hipaa: z.boolean().optional(),
authenticationPortal: z.boolean().optional(),
billing: z.boolean().optional(),
});
+1 -2
View File
@@ -1,8 +1,7 @@
import { OrganisationEmailSchema } from '@documenso/prisma/generated/zod/modelSchema/OrganisationEmailSchema';
import { EmailDomainStatus } from '@prisma/client';
import { z } from 'zod';
import { OrganisationEmailSchema } from '@documenso/prisma/generated/zod/modelSchema/OrganisationEmailSchema';
export const ZOrganisationEmailSchema = OrganisationEmailSchema.pick({
id: true,
createdAt: true,
+2 -5
View File
@@ -1,7 +1,6 @@
import { z } from 'zod';
import OrganisationClaimSchema from '@documenso/prisma/generated/zod/modelSchema/OrganisationClaimSchema';
import { OrganisationSchema } from '@documenso/prisma/generated/zod/modelSchema/OrganisationSchema';
import { z } from 'zod';
export const ZOrganisationSchema = OrganisationSchema.pick({
id: true,
@@ -56,6 +55,4 @@ export const ZOrganisationAccountLinkMetadataSchema = z.object({
}),
});
export type TOrganisationAccountLinkMetadata = z.infer<
typeof ZOrganisationAccountLinkMetadataSchema
>;
export type TOrganisationAccountLinkMetadata = z.infer<typeof ZOrganisationAccountLinkMetadataSchema>;
+19 -15
View File
@@ -1,10 +1,9 @@
import { msg } from '@lingui/core/macro';
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';
import { z } from 'zod';
import { zEmail } from '../utils/zod';
import { ZFieldSchema } from './field';
/**
@@ -23,7 +22,9 @@ export const ZRecipientSchema = RecipientSchema.pick({
name: true,
token: true,
documentDeletedAt: true,
expired: true,
expired: true, // deprecated Not in use. To be removed in a future migration.
expiresAt: true,
expirationNotifiedAt: true,
signedAt: true,
authOptions: true,
signingOrder: true,
@@ -50,7 +51,9 @@ export const ZRecipientLiteSchema = RecipientSchema.pick({
name: true,
token: true,
documentDeletedAt: true,
expired: true,
expired: true, // !: deprecated Not in use. To be removed in a future migration.
expiresAt: true,
expirationNotifiedAt: true,
signedAt: true,
authOptions: true,
signingOrder: true,
@@ -75,7 +78,9 @@ export const ZRecipientManySchema = RecipientSchema.pick({
name: true,
token: true,
documentDeletedAt: true,
expired: true,
expired: true, // !: deprecated Not in use. To be removed in a future migration.
expiresAt: true,
expirationNotifiedAt: true,
signedAt: true,
authOptions: true,
signingOrder: true,
@@ -112,12 +117,11 @@ export const ZEnvelopeRecipientManySchema = ZRecipientManySchema.omit({
templateId: true,
});
export const ZRecipientEmailSchema = z.union([
z.literal(''),
z
.string()
.trim()
.toLowerCase()
.email({ message: msg`Invalid email`.id })
.max(254),
]);
export type TRecipientSchema = z.infer<typeof ZRecipientSchema>;
export type TRecipientLite = z.infer<typeof ZRecipientLiteSchema>;
export type TRecipientMany = z.infer<typeof ZRecipientManySchema>;
export type TEnvelopeRecipientSchema = z.infer<typeof ZEnvelopeRecipientSchema>;
export type TEnvelopeRecipientLite = z.infer<typeof ZEnvelopeRecipientLiteSchema>;
export type TEnvelopeRecipientMany = z.infer<typeof ZEnvelopeRecipientManySchema>;
export const ZRecipientEmailSchema = z.union([z.literal(''), zEmail('Invalid email').trim().toLowerCase().max(254)]);
+20 -5
View File
@@ -1,8 +1,7 @@
import { ZOrganisationNameSchema } from '@documenso/trpc/server/organisation-router/create-organisation.types';
import type { SubscriptionClaim } from '@prisma/client';
import { z } from 'zod';
import { ZOrganisationNameSchema } from '@documenso/trpc/server/organisation-router/create-organisation.types';
/**
* README:
* - If you update this you MUST update the `backport-subscription-claims` schema as well.
@@ -29,11 +28,15 @@ export const ZClaimFlagsSchema = z.object({
cfr21: z.boolean().optional(),
hipaa: z.boolean().optional(),
authenticationPortal: z.boolean().optional(),
allowLegacyEnvelopes: z.boolean().optional(),
externalSigning2fa: z.boolean().optional(),
signingReminders: z.boolean().optional(),
});
export type TClaimFlags = z.infer<typeof ZClaimFlagsSchema>;
@@ -87,6 +90,11 @@ export const SUBSCRIPTION_CLAIM_FEATURE_FLAGS: Record<
label: '21 CFR',
isEnterprise: true,
},
hipaa: {
key: 'hipaa',
label: 'HIPAA',
isEnterprise: true,
},
authenticationPortal: {
key: 'authenticationPortal',
label: 'Authentication portal',
@@ -101,6 +109,10 @@ export const SUBSCRIPTION_CLAIM_FEATURE_FLAGS: Record<
label: 'External signing 2FA',
isEnterprise: true,
},
signingReminders: {
key: 'signingReminders',
label: 'Signing reminders',
},
};
export enum INTERNAL_CLAIM_ID {
@@ -137,6 +149,7 @@ export const internalClaims: InternalClaims = {
locked: true,
flags: {
unlimitedDocuments: true,
signingReminders: true,
},
},
[INTERNAL_CLAIM_ID.TEAM]: {
@@ -150,6 +163,7 @@ export const internalClaims: InternalClaims = {
unlimitedDocuments: true,
allowCustomBranding: true,
embedSigning: true,
signingReminders: true,
},
},
[INTERNAL_CLAIM_ID.PLATFORM]: {
@@ -168,6 +182,7 @@ export const internalClaims: InternalClaims = {
embedAuthoringWhiteLabel: true,
embedSigning: false,
embedSigningWhiteLabel: true,
signingReminders: true,
},
},
[INTERNAL_CLAIM_ID.ENTERPRISE]: {
@@ -188,6 +203,7 @@ export const internalClaims: InternalClaims = {
embedSigningWhiteLabel: true,
cfr21: true,
authenticationPortal: true,
signingReminders: true,
},
},
[INTERNAL_CLAIM_ID.EARLY_ADOPTER]: {
@@ -203,6 +219,7 @@ export const internalClaims: InternalClaims = {
hidePoweredBy: true,
embedSigning: true,
embedSigningWhiteLabel: true,
signingReminders: true,
},
},
} as const;
@@ -212,6 +229,4 @@ export const ZStripeOrganisationCreateMetadataSchema = z.object({
userId: z.number(),
});
export type StripeOrganisationCreateMetadata = z.infer<
typeof ZStripeOrganisationCreateMetadataSchema
>;
export type StripeOrganisationCreateMetadata = z.infer<typeof ZStripeOrganisationCreateMetadataSchema>;
+3 -6
View File
@@ -1,15 +1,11 @@
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 { 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 {
LegacyTemplateDirectLinkSchema,
TemplateSchema,
} from '@documenso/prisma/types/template-legacy-schema';
import { LegacyTemplateDirectLinkSchema, TemplateSchema } from '@documenso/prisma/types/template-legacy-schema';
import { z } from 'zod';
import { ZFieldSchema } from './field';
import { ZRecipientLiteSchema } from './recipient';
@@ -146,6 +142,7 @@ export const ZTemplateManySchema = TemplateSchema.pick({
team: TeamSchema.pick({
id: true,
url: true,
name: true,
}).nullable(),
fields: ZFieldSchema.array(),
recipients: ZRecipientLiteSchema.array(),
+24 -16
View File
@@ -1,4 +1,4 @@
import type { DocumentMeta, Envelope, Recipient, WebhookTriggerEvents } from '@prisma/client';
import type { DocumentMeta, Envelope, Recipient } from '@prisma/client';
import {
DocumentDistributionMethod,
DocumentSigningOrder,
@@ -10,6 +10,7 @@ import {
RecipientRole,
SendStatus,
SigningStatus,
WebhookTriggerEvents,
} from '@prisma/client';
import { z } from 'zod';
@@ -25,9 +26,10 @@ export const ZWebhookRecipientSchema = z.object({
email: z.string(),
name: z.string(),
token: z.string(),
documentDeletedAt: z.date().nullable(),
expired: z.date().nullable(),
signedAt: z.date().nullable(),
documentDeletedAt: z.coerce.date().nullable(),
expiresAt: z.coerce.date().nullable(),
expirationNotifiedAt: z.coerce.date().nullable(),
signedAt: z.coerce.date().nullable(),
authOptions: z.any().nullable(),
signingOrder: z.number().nullable(),
rejectionReason: z.string().nullable(),
@@ -69,10 +71,10 @@ export const ZWebhookDocumentSchema = z.object({
visibility: z.nativeEnum(DocumentVisibility),
title: z.string(),
status: z.nativeEnum(DocumentStatus),
createdAt: z.date(),
updatedAt: z.date(),
completedAt: z.date().nullable(),
deletedAt: z.date().nullable(),
createdAt: z.coerce.date(),
updatedAt: z.coerce.date(),
completedAt: z.coerce.date().nullable(),
deletedAt: z.coerce.date().nullable(),
teamId: z.number().nullable(),
templateId: z.number().nullable(),
source: z.nativeEnum(DocumentSource),
@@ -85,15 +87,20 @@ export const ZWebhookDocumentSchema = z.object({
Recipient: z.array(ZWebhookRecipientSchema),
});
/**
* Schema for the full webhook delivery envelope (what receivers see on the wire
* and what is persisted to `WebhookCall.requestBody`).
*/
export const ZWebhookPayloadSchema = z.object({
event: z.nativeEnum(WebhookTriggerEvents),
payload: ZWebhookDocumentSchema,
createdAt: z.string(),
webhookEndpoint: z.string(),
});
export type TWebhookRecipient = z.infer<typeof ZWebhookRecipientSchema>;
export type TWebhookDocument = z.infer<typeof ZWebhookDocumentSchema>;
export type WebhookPayload = {
event: WebhookTriggerEvents;
payload: TWebhookDocument;
createdAt: string;
webhookEndpoint: string;
};
export type WebhookPayload = z.infer<typeof ZWebhookPayloadSchema>;
export const mapEnvelopeToWebhookDocumentPayload = (
envelope: Envelope & {
@@ -116,7 +123,8 @@ export const mapEnvelopeToWebhookDocumentPayload = (
name: recipient.name,
token: recipient.token,
documentDeletedAt: recipient.documentDeletedAt,
expired: recipient.expired,
expiresAt: recipient.expiresAt,
expirationNotifiedAt: recipient.expirationNotifiedAt,
signedAt: recipient.signedAt,
authOptions: recipient.authOptions,
signingOrder: recipient.signingOrder,