chore: merged main

This commit is contained in:
Catalin Pit
2025-07-23 14:03:30 +03:00
93 changed files with 12721 additions and 546 deletions

View File

@ -12,7 +12,7 @@ import { ZCreateSubscriptionRequestSchema } from './create-subscription.types';
export const createSubscriptionRoute = authenticatedProcedure
.input(ZCreateSubscriptionRequestSchema)
.mutation(async ({ ctx, input }) => {
const { organisationId, priceId } = input;
const { organisationId, priceId, isPersonalLayoutMode } = input;
ctx.logger.info({
input: {
@ -70,10 +70,14 @@ export const createSubscriptionRoute = authenticatedProcedure
});
}
const returnUrl = isPersonalLayoutMode
? `${NEXT_PUBLIC_WEBAPP_URL()}/settings/billing`
: `${NEXT_PUBLIC_WEBAPP_URL()}/o/${organisation.url}/settings/billing`;
const redirectUrl = await createCheckoutSession({
customerId,
priceId,
returnUrl: `${NEXT_PUBLIC_WEBAPP_URL()}/o/${organisation.url}/settings/billing`,
returnUrl,
});
if (!redirectUrl) {

View File

@ -3,4 +3,5 @@ import { z } from 'zod';
export const ZCreateSubscriptionRequestSchema = z.object({
organisationId: z.string().describe('The organisation to create the subscription for'),
priceId: z.string().describe('The price to create the subscription for'),
isPersonalLayoutMode: z.boolean().optional(),
});

View File

@ -322,7 +322,7 @@ export const documentRouter = router({
return {
document: createdDocument,
folder: createdDocument.folder,
folder: createdDocument.folder, // Todo: Remove this prior to api-v2 release.
uploadUrl: url,
};
}),

View File

@ -33,7 +33,9 @@ export const createEmbeddingTemplateRoute = procedure
// First create the template
const template = await createTemplate({
userId: apiToken.userId,
title,
data: {
title,
},
templateDocumentDataId: documentDataId,
teamId: apiToken.teamId ?? undefined,
});

View File

@ -1,9 +1,11 @@
import type { Document } from '@prisma/client';
import { DocumentDataType } from '@prisma/client';
import { TRPCError } from '@trpc/server';
import { getServerLimits } from '@documenso/ee/server-only/limits/server';
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
import { jobs } from '@documenso/lib/jobs/client';
import { createDocumentData } from '@documenso/lib/server-only/document-data/create-document-data';
import { getDocumentWithDetailsById } from '@documenso/lib/server-only/document/get-document-with-details-by-id';
import { sendDocument } from '@documenso/lib/server-only/document/send-document';
import {
@ -23,6 +25,7 @@ import { findTemplates } from '@documenso/lib/server-only/template/find-template
import { getTemplateById } from '@documenso/lib/server-only/template/get-template-by-id';
import { toggleTemplateDirectLink } from '@documenso/lib/server-only/template/toggle-template-direct-link';
import { updateTemplate } from '@documenso/lib/server-only/template/update-template';
import { getPresignPostUrl } from '@documenso/lib/universal/upload/server-actions';
import { ZGenericSuccessResponse, ZSuccessResponseSchema } from '../document-router/schema';
import { authenticatedProcedure, maybeAuthenticatedProcedure, router } from '../trpc';
@ -34,6 +37,8 @@ import {
ZCreateTemplateDirectLinkRequestSchema,
ZCreateTemplateDirectLinkResponseSchema,
ZCreateTemplateMutationSchema,
ZCreateTemplateV2RequestSchema,
ZCreateTemplateV2ResponseSchema,
ZDeleteTemplateDirectLinkRequestSchema,
ZDeleteTemplateMutationSchema,
ZDuplicateTemplateMutationSchema,
@ -141,12 +146,88 @@ export const templateRouter = router({
return await createTemplate({
userId: ctx.user.id,
teamId,
title,
templateDocumentDataId,
folderId,
data: {
title,
folderId,
},
});
}),
/**
* Temporariy endpoint for V2 Beta until we allow passthrough documents on create.
*
* @public
* @deprecated
*/
createTemplateTemporary: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/template/create/beta',
summary: 'Create template',
description:
'You will need to upload the PDF to the provided URL returned. Note: Once V2 API is released, this will be removed since we will allow direct uploads, instead of using an upload URL.',
tags: ['Template'],
},
})
.input(ZCreateTemplateV2RequestSchema)
.output(ZCreateTemplateV2ResponseSchema)
.mutation(async ({ input, ctx }) => {
const { teamId, user } = ctx;
const {
title,
folderId,
externalId,
visibility,
globalAccessAuth,
globalActionAuth,
publicTitle,
publicDescription,
type,
meta,
} = input;
const fileName = title.endsWith('.pdf') ? title : `${title}.pdf`;
const { url, key } = await getPresignPostUrl(fileName, 'application/pdf');
const templateDocumentData = await createDocumentData({
data: key,
type: DocumentDataType.S3_PATH,
});
const createdTemplate = await createTemplate({
userId: user.id,
teamId,
templateDocumentDataId: templateDocumentData.id,
data: {
title,
folderId,
externalId,
visibility,
globalAccessAuth,
globalActionAuth,
publicTitle,
publicDescription,
type,
},
meta,
});
const fullTemplate = await getTemplateById({
id: createdTemplate.id,
userId: user.id,
teamId,
});
return {
template: fullTemplate,
uploadUrl: url,
};
}),
/**
* @public
*/

View File

@ -30,6 +30,50 @@ import {
} from '../document-router/schema';
import { ZSignFieldWithTokenMutationSchema } from '../field-router/schema';
export const MAX_TEMPLATE_PUBLIC_TITLE_LENGTH = 50;
export const MAX_TEMPLATE_PUBLIC_DESCRIPTION_LENGTH = 256;
export const ZTemplateTitleSchema = z
.string()
.trim()
.min(1)
.max(255)
.describe('The title of the document.');
export const ZTemplatePublicTitleSchema = z
.string()
.trim()
.min(1)
.max(MAX_TEMPLATE_PUBLIC_TITLE_LENGTH)
.describe(
'The title of the template that will be displayed to the public. Only applicable for public templates.',
);
export const ZTemplatePublicDescriptionSchema = z
.string()
.trim()
.min(1)
.max(MAX_TEMPLATE_PUBLIC_DESCRIPTION_LENGTH)
.describe(
'The description of the template that will be displayed to the public. Only applicable for public templates.',
);
export const ZTemplateMetaUpsertSchema = z.object({
subject: ZDocumentMetaSubjectSchema.optional(),
message: ZDocumentMetaMessageSchema.optional(),
timezone: ZDocumentMetaTimezoneSchema.optional(),
dateFormat: ZDocumentMetaDateFormatSchema.optional(),
distributionMethod: ZDocumentMetaDistributionMethodSchema.optional(),
emailSettings: ZDocumentEmailSettingsSchema.optional(),
redirectUrl: ZDocumentMetaRedirectUrlSchema.optional(),
language: ZDocumentMetaLanguageSchema.optional(),
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
allowDictateNextSigner: z.boolean().optional(),
});
export const ZCreateTemplateMutationSchema = z.object({
title: z.string().min(1).trim(),
templateDocumentDataId: z.string().min(1),
@ -123,57 +167,46 @@ export const ZDeleteTemplateMutationSchema = z.object({
templateId: z.number(),
});
export const MAX_TEMPLATE_PUBLIC_TITLE_LENGTH = 50;
export const MAX_TEMPLATE_PUBLIC_DESCRIPTION_LENGTH = 256;
/**
* Note: This is the same between V1 and V2. Be careful when updating this schema and think of the consequences.
*/
export const ZCreateTemplateV2RequestSchema = z.object({
title: ZTemplateTitleSchema,
folderId: z.string().optional(),
externalId: z.string().nullish(),
visibility: z.nativeEnum(DocumentVisibility).optional(),
globalAccessAuth: z.array(ZDocumentAccessAuthTypesSchema).optional().default([]),
globalActionAuth: z.array(ZDocumentActionAuthTypesSchema).optional().default([]),
publicTitle: ZTemplatePublicTitleSchema.optional(),
publicDescription: ZTemplatePublicDescriptionSchema.optional(),
type: z.nativeEnum(TemplateType).optional(),
meta: ZTemplateMetaUpsertSchema.optional(),
});
/**
* Note: This is the same between V1 and V2. Be careful when updating this schema and think of the consequences.
*/
export const ZCreateTemplateV2ResponseSchema = z.object({
template: ZTemplateSchema,
uploadUrl: z.string().min(1),
});
export const ZUpdateTemplateRequestSchema = z.object({
templateId: z.number(),
data: z
.object({
title: z.string().min(1).optional(),
title: ZTemplateTitleSchema.optional(),
externalId: z.string().nullish(),
visibility: z.nativeEnum(DocumentVisibility).optional(),
globalAccessAuth: z.array(ZDocumentAccessAuthTypesSchema).optional().default([]),
globalActionAuth: z.array(ZDocumentActionAuthTypesSchema).optional().default([]),
publicTitle: z
.string()
.trim()
.min(1)
.max(MAX_TEMPLATE_PUBLIC_TITLE_LENGTH)
.describe(
'The title of the template that will be displayed to the public. Only applicable for public templates.',
)
.optional(),
publicDescription: z
.string()
.trim()
.min(1)
.max(MAX_TEMPLATE_PUBLIC_DESCRIPTION_LENGTH)
.describe(
'The description of the template that will be displayed to the public. Only applicable for public templates.',
)
.optional(),
publicTitle: ZTemplatePublicTitleSchema.optional(),
publicDescription: ZTemplatePublicDescriptionSchema.optional(),
type: z.nativeEnum(TemplateType).optional(),
useLegacyFieldInsertion: z.boolean().optional(),
})
.optional(),
meta: z
.object({
subject: ZDocumentMetaSubjectSchema.optional(),
message: ZDocumentMetaMessageSchema.optional(),
timezone: ZDocumentMetaTimezoneSchema.optional(),
dateFormat: ZDocumentMetaDateFormatSchema.optional(),
distributionMethod: ZDocumentMetaDistributionMethodSchema.optional(),
emailSettings: ZDocumentEmailSettingsSchema.optional(),
redirectUrl: ZDocumentMetaRedirectUrlSchema.optional(),
language: ZDocumentMetaLanguageSchema.optional(),
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
allowDictateNextSigner: z.boolean().optional(),
})
.optional(),
meta: ZTemplateMetaUpsertSchema.optional(),
});
export const ZUpdateTemplateResponseSchema = ZTemplateLiteSchema;

View File

@ -3,6 +3,7 @@ import { deleteWebhookById } from '@documenso/lib/server-only/webhooks/delete-we
import { editWebhook } from '@documenso/lib/server-only/webhooks/edit-webhook';
import { getWebhookById } from '@documenso/lib/server-only/webhooks/get-webhook-by-id';
import { getWebhooksByTeamId } from '@documenso/lib/server-only/webhooks/get-webhooks-by-team-id';
import { triggerTestWebhook } from '@documenso/lib/server-only/webhooks/trigger-test-webhook';
import { authenticatedProcedure, router } from '../trpc';
import {
@ -11,6 +12,7 @@ import {
ZEditWebhookRequestSchema,
ZGetTeamWebhooksRequestSchema,
ZGetWebhookByIdRequestSchema,
ZTriggerTestWebhookRequestSchema,
} from './schema';
export const webhookRouter = router({
@ -106,4 +108,25 @@ export const webhookRouter = router({
teamId,
});
}),
testWebhook: authenticatedProcedure
.input(ZTriggerTestWebhookRequestSchema)
.mutation(async ({ input, ctx }) => {
const { id, event, teamId } = input;
ctx.logger.info({
input: {
id,
event,
teamId,
},
});
return await triggerTestWebhook({
id,
event,
userId: ctx.user.id,
teamId,
});
}),
});

View File

@ -38,3 +38,11 @@ export const ZDeleteWebhookRequestSchema = z.object({
});
export type TDeleteWebhookRequestSchema = z.infer<typeof ZDeleteWebhookRequestSchema>;
export const ZTriggerTestWebhookRequestSchema = z.object({
id: z.string(),
event: z.nativeEnum(WebhookTriggerEvents),
teamId: z.number(),
});
export type TTriggerTestWebhookRequestSchema = z.infer<typeof ZTriggerTestWebhookRequestSchema>;