mirror of
https://github.com/documenso/documenso.git
synced 2025-11-12 15:53:02 +10:00
feat: support embedded authoring for creation (#1741)
Adds support for creating documents and templates using our embed components. Support is super primitive at the moment and is being polished.
This commit is contained in:
14
packages/trpc/server/embedding-router/_router.ts
Normal file
14
packages/trpc/server/embedding-router/_router.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { router } from '../trpc';
|
||||
import { createEmbeddingDocumentRoute } from './create-embedding-document';
|
||||
import { createEmbeddingPresignTokenRoute } from './create-embedding-presign-token';
|
||||
import { createEmbeddingTemplateRoute } from './create-embedding-template';
|
||||
import { getEmbeddingDocumentRoute } from './get-embedding-document';
|
||||
import { verifyEmbeddingPresignTokenRoute } from './verify-embedding-presign-token';
|
||||
|
||||
export const embeddingPresignRouter = router({
|
||||
createEmbeddingPresignToken: createEmbeddingPresignTokenRoute,
|
||||
verifyEmbeddingPresignToken: verifyEmbeddingPresignTokenRoute,
|
||||
createEmbeddingDocument: createEmbeddingDocumentRoute,
|
||||
createEmbeddingTemplate: createEmbeddingTemplateRoute,
|
||||
getEmbeddingDocument: getEmbeddingDocumentRoute,
|
||||
});
|
||||
@ -0,0 +1,63 @@
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { createDocumentV2 } from '@documenso/lib/server-only/document/create-document-v2';
|
||||
import { verifyEmbeddingPresignToken } from '@documenso/lib/server-only/embedding-presign/verify-embedding-presign-token';
|
||||
|
||||
import { procedure } from '../trpc';
|
||||
import {
|
||||
ZCreateEmbeddingDocumentRequestSchema,
|
||||
ZCreateEmbeddingDocumentResponseSchema,
|
||||
} from './create-embedding-document.types';
|
||||
|
||||
export const createEmbeddingDocumentRoute = procedure
|
||||
.input(ZCreateEmbeddingDocumentRequestSchema)
|
||||
.output(ZCreateEmbeddingDocumentResponseSchema)
|
||||
.mutation(async ({ input, ctx: { req, metadata } }) => {
|
||||
try {
|
||||
const authorizationHeader = req.headers.get('authorization');
|
||||
|
||||
const [presignToken] = (authorizationHeader || '')
|
||||
.split('Bearer ')
|
||||
.filter((s) => s.length > 0);
|
||||
|
||||
if (!presignToken) {
|
||||
throw new AppError(AppErrorCode.UNAUTHORIZED, {
|
||||
message: 'No presign token provided',
|
||||
});
|
||||
}
|
||||
|
||||
const apiToken = await verifyEmbeddingPresignToken({ token: presignToken });
|
||||
|
||||
const { title, documentDataId, externalId, recipients, meta } = input;
|
||||
|
||||
const document = await createDocumentV2({
|
||||
data: {
|
||||
title,
|
||||
externalId,
|
||||
recipients,
|
||||
},
|
||||
meta,
|
||||
documentDataId,
|
||||
userId: apiToken.userId,
|
||||
teamId: apiToken.teamId ?? undefined,
|
||||
requestMetadata: metadata,
|
||||
});
|
||||
|
||||
if (!document.id) {
|
||||
throw new AppError(AppErrorCode.UNKNOWN_ERROR, {
|
||||
message: 'Failed to create document: missing document ID',
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
documentId: document.id,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new AppError(AppErrorCode.UNKNOWN_ERROR, {
|
||||
message: 'Failed to create document',
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,83 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email';
|
||||
import {
|
||||
ZFieldHeightSchema,
|
||||
ZFieldPageNumberSchema,
|
||||
ZFieldPageXSchema,
|
||||
ZFieldPageYSchema,
|
||||
ZFieldWidthSchema,
|
||||
} from '@documenso/lib/types/field';
|
||||
import { ZFieldAndMetaSchema } from '@documenso/lib/types/field-meta';
|
||||
import { DocumentSigningOrder } from '@documenso/prisma/generated/types';
|
||||
|
||||
import {
|
||||
ZDocumentExternalIdSchema,
|
||||
ZDocumentMetaDateFormatSchema,
|
||||
ZDocumentMetaDistributionMethodSchema,
|
||||
ZDocumentMetaDrawSignatureEnabledSchema,
|
||||
ZDocumentMetaLanguageSchema,
|
||||
ZDocumentMetaMessageSchema,
|
||||
ZDocumentMetaRedirectUrlSchema,
|
||||
ZDocumentMetaSubjectSchema,
|
||||
ZDocumentMetaTimezoneSchema,
|
||||
ZDocumentMetaTypedSignatureEnabledSchema,
|
||||
ZDocumentMetaUploadSignatureEnabledSchema,
|
||||
ZDocumentTitleSchema,
|
||||
} from '../document-router/schema';
|
||||
import { ZCreateRecipientSchema } from '../recipient-router/schema';
|
||||
|
||||
export const ZCreateEmbeddingDocumentRequestSchema = z.object({
|
||||
title: ZDocumentTitleSchema,
|
||||
documentDataId: z.string(),
|
||||
externalId: ZDocumentExternalIdSchema.optional(),
|
||||
recipients: z
|
||||
.array(
|
||||
ZCreateRecipientSchema.extend({
|
||||
fields: ZFieldAndMetaSchema.and(
|
||||
z.object({
|
||||
pageNumber: ZFieldPageNumberSchema,
|
||||
pageX: ZFieldPageXSchema,
|
||||
pageY: ZFieldPageYSchema,
|
||||
width: ZFieldWidthSchema,
|
||||
height: ZFieldHeightSchema,
|
||||
}),
|
||||
)
|
||||
.array()
|
||||
.optional(),
|
||||
}),
|
||||
)
|
||||
.refine(
|
||||
(recipients) => {
|
||||
const emails = recipients.map((recipient) => recipient.email);
|
||||
|
||||
return new Set(emails).size === emails.length;
|
||||
},
|
||||
{ message: 'Recipients must have unique emails' },
|
||||
)
|
||||
.optional(),
|
||||
meta: z
|
||||
.object({
|
||||
subject: ZDocumentMetaSubjectSchema.optional(),
|
||||
message: ZDocumentMetaMessageSchema.optional(),
|
||||
timezone: ZDocumentMetaTimezoneSchema.optional(),
|
||||
dateFormat: ZDocumentMetaDateFormatSchema.optional(),
|
||||
distributionMethod: ZDocumentMetaDistributionMethodSchema.optional(),
|
||||
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
|
||||
redirectUrl: ZDocumentMetaRedirectUrlSchema.optional(),
|
||||
language: ZDocumentMetaLanguageSchema.optional(),
|
||||
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
||||
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
||||
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
||||
emailSettings: ZDocumentEmailSettingsSchema.optional(),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export const ZCreateEmbeddingDocumentResponseSchema = z.object({
|
||||
documentId: z.number(),
|
||||
});
|
||||
|
||||
export type TCreateEmbeddingDocumentRequestSchema = z.infer<
|
||||
typeof ZCreateEmbeddingDocumentRequestSchema
|
||||
>;
|
||||
@ -0,0 +1,73 @@
|
||||
import { isCommunityPlan } from '@documenso/ee/server-only/util/is-community-plan';
|
||||
import { isUserEnterprise } from '@documenso/ee/server-only/util/is-document-enterprise';
|
||||
import { isDocumentPlatform } from '@documenso/ee/server-only/util/is-document-platform';
|
||||
import { IS_BILLING_ENABLED } from '@documenso/lib/constants/app';
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { createEmbeddingPresignToken } from '@documenso/lib/server-only/embedding-presign/create-embedding-presign-token';
|
||||
import { getApiTokenByToken } from '@documenso/lib/server-only/public-api/get-api-token-by-token';
|
||||
|
||||
import { procedure } from '../trpc';
|
||||
import {
|
||||
ZCreateEmbeddingPresignTokenRequestSchema,
|
||||
ZCreateEmbeddingPresignTokenResponseSchema,
|
||||
createEmbeddingPresignTokenMeta,
|
||||
} from './create-embedding-presign-token.types';
|
||||
|
||||
/**
|
||||
* Route to create embedding presign tokens.
|
||||
*/
|
||||
export const createEmbeddingPresignTokenRoute = procedure
|
||||
.meta(createEmbeddingPresignTokenMeta)
|
||||
.input(ZCreateEmbeddingPresignTokenRequestSchema)
|
||||
.output(ZCreateEmbeddingPresignTokenResponseSchema)
|
||||
.mutation(async ({ input, ctx: { req } }) => {
|
||||
try {
|
||||
const authorizationHeader = req.headers.get('authorization');
|
||||
const [apiToken] = (authorizationHeader || '').split('Bearer ').filter((s) => s.length > 0);
|
||||
|
||||
if (!apiToken) {
|
||||
throw new AppError(AppErrorCode.UNAUTHORIZED, {
|
||||
message: 'No API token provided',
|
||||
});
|
||||
}
|
||||
|
||||
const { expiresIn } = input;
|
||||
|
||||
if (IS_BILLING_ENABLED()) {
|
||||
const token = await getApiTokenByToken({ token: apiToken });
|
||||
|
||||
if (!token.userId) {
|
||||
throw new AppError(AppErrorCode.UNAUTHORIZED, {
|
||||
message: 'Invalid API token',
|
||||
});
|
||||
}
|
||||
|
||||
const [hasCommunityPlan, hasPlatformPlan, hasEnterprisePlan] = await Promise.all([
|
||||
isCommunityPlan({ userId: token.userId, teamId: token.teamId ?? undefined }),
|
||||
isDocumentPlatform({ userId: token.userId, teamId: token.teamId }),
|
||||
isUserEnterprise({ userId: token.userId, teamId: token.teamId ?? undefined }),
|
||||
]);
|
||||
|
||||
if (!hasCommunityPlan && !hasPlatformPlan && !hasEnterprisePlan) {
|
||||
throw new AppError(AppErrorCode.UNAUTHORIZED, {
|
||||
message: 'You do not have permission to create embedding presign tokens',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const presignToken = await createEmbeddingPresignToken({
|
||||
apiToken,
|
||||
expiresIn,
|
||||
});
|
||||
|
||||
return { ...presignToken };
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new AppError(AppErrorCode.UNKNOWN_ERROR, {
|
||||
message: 'Failed to create embedding presign token',
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,38 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import type { TrpcRouteMeta } from '../trpc';
|
||||
|
||||
export const createEmbeddingPresignTokenMeta: TrpcRouteMeta = {
|
||||
openapi: {
|
||||
method: 'POST',
|
||||
path: '/embedding/create-presign-token',
|
||||
summary: 'Create embedding presign token',
|
||||
description:
|
||||
'Creates a presign token for embedding operations with configurable expiration time',
|
||||
tags: ['Embedding'],
|
||||
},
|
||||
};
|
||||
|
||||
export const ZCreateEmbeddingPresignTokenRequestSchema = z.object({
|
||||
expiresIn: z
|
||||
.number()
|
||||
.min(0)
|
||||
.max(10080)
|
||||
.optional()
|
||||
.default(60)
|
||||
.describe('Expiration time in minutes (default: 60, max: 10,080)'),
|
||||
});
|
||||
|
||||
export const ZCreateEmbeddingPresignTokenResponseSchema = z.object({
|
||||
token: z.string(),
|
||||
expiresAt: z.date(),
|
||||
expiresIn: z.number().describe('Expiration time in seconds'),
|
||||
});
|
||||
|
||||
export type TCreateEmbeddingPresignTokenRequestSchema = z.infer<
|
||||
typeof ZCreateEmbeddingPresignTokenRequestSchema
|
||||
>;
|
||||
|
||||
export type TCreateEmbeddingPresignTokenResponseSchema = z.infer<
|
||||
typeof ZCreateEmbeddingPresignTokenResponseSchema
|
||||
>;
|
||||
@ -0,0 +1,112 @@
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { verifyEmbeddingPresignToken } from '@documenso/lib/server-only/embedding-presign/verify-embedding-presign-token';
|
||||
import { createTemplate } from '@documenso/lib/server-only/template/create-template';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
import { procedure } from '../trpc';
|
||||
import {
|
||||
ZCreateEmbeddingTemplateRequestSchema,
|
||||
ZCreateEmbeddingTemplateResponseSchema,
|
||||
} from './create-embedding-template.types';
|
||||
|
||||
export const createEmbeddingTemplateRoute = procedure
|
||||
.input(ZCreateEmbeddingTemplateRequestSchema)
|
||||
.output(ZCreateEmbeddingTemplateResponseSchema)
|
||||
.mutation(async ({ input, ctx: { req } }) => {
|
||||
try {
|
||||
const authorizationHeader = req.headers.get('authorization');
|
||||
|
||||
const [presignToken] = (authorizationHeader || '')
|
||||
.split('Bearer ')
|
||||
.filter((s) => s.length > 0);
|
||||
|
||||
if (!presignToken) {
|
||||
throw new AppError(AppErrorCode.UNAUTHORIZED, {
|
||||
message: 'No presign token provided',
|
||||
});
|
||||
}
|
||||
|
||||
const apiToken = await verifyEmbeddingPresignToken({ token: presignToken });
|
||||
|
||||
const { title, documentDataId, recipients, meta } = input;
|
||||
|
||||
// First create the template
|
||||
const template = await createTemplate({
|
||||
userId: apiToken.userId,
|
||||
title,
|
||||
templateDocumentDataId: documentDataId,
|
||||
teamId: apiToken.teamId ?? undefined,
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
recipients.map(async (recipient) => {
|
||||
const createdRecipient = await prisma.recipient.create({
|
||||
data: {
|
||||
templateId: template.id,
|
||||
email: recipient.email,
|
||||
name: recipient.name || '',
|
||||
role: recipient.role || 'SIGNER',
|
||||
token: `template-${template.id}-${recipient.email}`,
|
||||
signingOrder: recipient.signingOrder,
|
||||
},
|
||||
});
|
||||
|
||||
const fields = recipient.fields ?? [];
|
||||
|
||||
const createdFields = await prisma.field.createMany({
|
||||
data: fields.map((field) => ({
|
||||
recipientId: createdRecipient.id,
|
||||
type: field.type,
|
||||
page: field.pageNumber,
|
||||
positionX: field.pageX,
|
||||
positionY: field.pageY,
|
||||
width: field.width,
|
||||
height: field.height,
|
||||
customText: '',
|
||||
inserted: false,
|
||||
templateId: template.id,
|
||||
})),
|
||||
});
|
||||
|
||||
return {
|
||||
...createdRecipient,
|
||||
fields: createdFields,
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
// Update the template meta if needed
|
||||
if (meta) {
|
||||
await prisma.templateMeta.upsert({
|
||||
where: {
|
||||
templateId: template.id,
|
||||
},
|
||||
create: {
|
||||
templateId: template.id,
|
||||
...meta,
|
||||
},
|
||||
update: {
|
||||
...meta,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (!template.id) {
|
||||
throw new AppError(AppErrorCode.UNKNOWN_ERROR, {
|
||||
message: 'Failed to create template: missing template ID',
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
templateId: template.id,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new AppError(AppErrorCode.UNKNOWN_ERROR, {
|
||||
message: 'Failed to create template',
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,74 @@
|
||||
import { DocumentSigningOrder, FieldType, RecipientRole } from '@prisma/client';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email';
|
||||
import {
|
||||
ZFieldHeightSchema,
|
||||
ZFieldPageNumberSchema,
|
||||
ZFieldPageXSchema,
|
||||
ZFieldPageYSchema,
|
||||
ZFieldWidthSchema,
|
||||
} from '@documenso/lib/types/field';
|
||||
import { ZFieldMetaSchema } from '@documenso/lib/types/field-meta';
|
||||
|
||||
import {
|
||||
ZDocumentMetaDateFormatSchema,
|
||||
ZDocumentMetaDistributionMethodSchema,
|
||||
ZDocumentMetaDrawSignatureEnabledSchema,
|
||||
ZDocumentMetaLanguageSchema,
|
||||
ZDocumentMetaMessageSchema,
|
||||
ZDocumentMetaRedirectUrlSchema,
|
||||
ZDocumentMetaSubjectSchema,
|
||||
ZDocumentMetaTimezoneSchema,
|
||||
ZDocumentMetaTypedSignatureEnabledSchema,
|
||||
ZDocumentMetaUploadSignatureEnabledSchema,
|
||||
ZDocumentTitleSchema,
|
||||
} from '../document-router/schema';
|
||||
|
||||
const ZFieldSchema = z.object({
|
||||
type: z.nativeEnum(FieldType),
|
||||
pageNumber: ZFieldPageNumberSchema,
|
||||
pageX: ZFieldPageXSchema,
|
||||
pageY: ZFieldPageYSchema,
|
||||
width: ZFieldWidthSchema,
|
||||
height: ZFieldHeightSchema,
|
||||
fieldMeta: ZFieldMetaSchema.optional(),
|
||||
});
|
||||
|
||||
export const ZCreateEmbeddingTemplateRequestSchema = z.object({
|
||||
title: ZDocumentTitleSchema,
|
||||
documentDataId: z.string(),
|
||||
recipients: z.array(
|
||||
z.object({
|
||||
email: z.string().email(),
|
||||
name: z.string().optional(),
|
||||
role: z.nativeEnum(RecipientRole).optional(),
|
||||
signingOrder: z.number().optional(),
|
||||
fields: z.array(ZFieldSchema).optional(),
|
||||
}),
|
||||
),
|
||||
meta: z
|
||||
.object({
|
||||
subject: ZDocumentMetaSubjectSchema.optional(),
|
||||
message: ZDocumentMetaMessageSchema.optional(),
|
||||
timezone: ZDocumentMetaTimezoneSchema.optional(),
|
||||
dateFormat: ZDocumentMetaDateFormatSchema.optional(),
|
||||
distributionMethod: ZDocumentMetaDistributionMethodSchema.optional(),
|
||||
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
|
||||
redirectUrl: ZDocumentMetaRedirectUrlSchema.optional(),
|
||||
language: ZDocumentMetaLanguageSchema.optional(),
|
||||
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
||||
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
||||
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
||||
emailSettings: ZDocumentEmailSettingsSchema.optional(),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export const ZCreateEmbeddingTemplateResponseSchema = z.object({
|
||||
templateId: z.number(),
|
||||
});
|
||||
|
||||
export type TCreateEmbeddingTemplateRequestSchema = z.infer<
|
||||
typeof ZCreateEmbeddingTemplateRequestSchema
|
||||
>;
|
||||
@ -0,0 +1,63 @@
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { verifyEmbeddingPresignToken } from '@documenso/lib/server-only/embedding-presign/verify-embedding-presign-token';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
import { procedure } from '../trpc';
|
||||
import {
|
||||
ZGetEmbeddingDocumentRequestSchema,
|
||||
ZGetEmbeddingDocumentResponseSchema,
|
||||
} from './get-embedding-document.types';
|
||||
|
||||
export const getEmbeddingDocumentRoute = procedure
|
||||
.input(ZGetEmbeddingDocumentRequestSchema)
|
||||
.output(ZGetEmbeddingDocumentResponseSchema)
|
||||
.query(async ({ input, ctx: { req } }) => {
|
||||
try {
|
||||
const authorizationHeader = req.headers.get('authorization');
|
||||
|
||||
const [presignToken] = (authorizationHeader || '')
|
||||
.split('Bearer ')
|
||||
.filter((s) => s.length > 0);
|
||||
|
||||
if (!presignToken) {
|
||||
throw new AppError(AppErrorCode.UNAUTHORIZED, {
|
||||
message: 'No presign token provided',
|
||||
});
|
||||
}
|
||||
|
||||
const apiToken = await verifyEmbeddingPresignToken({ token: presignToken });
|
||||
|
||||
const { documentId } = input;
|
||||
|
||||
const document = await prisma.document.findFirst({
|
||||
where: {
|
||||
id: documentId,
|
||||
userId: apiToken.userId,
|
||||
...(apiToken.teamId ? { teamId: apiToken.teamId } : {}),
|
||||
},
|
||||
include: {
|
||||
documentData: true,
|
||||
recipients: true,
|
||||
fields: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!document) {
|
||||
throw new AppError(AppErrorCode.NOT_FOUND, {
|
||||
message: 'Document not found',
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
document,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new AppError(AppErrorCode.UNKNOWN_ERROR, {
|
||||
message: 'Failed to get document',
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,34 @@
|
||||
import { DocumentDataType, type Field, type Recipient } from '@prisma/client';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const ZGetEmbeddingDocumentRequestSchema = z.object({
|
||||
documentId: z.number(),
|
||||
});
|
||||
|
||||
export const ZGetEmbeddingDocumentResponseSchema = z.object({
|
||||
document: z
|
||||
.object({
|
||||
id: z.number(),
|
||||
title: z.string(),
|
||||
status: z.string(),
|
||||
documentDataId: z.string(),
|
||||
userId: z.number(),
|
||||
teamId: z.number().nullable(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
documentData: z.object({
|
||||
id: z.string(),
|
||||
type: z.nativeEnum(DocumentDataType),
|
||||
data: z.string(),
|
||||
initialData: z.string(),
|
||||
}),
|
||||
recipients: z.array(z.custom<Recipient>()),
|
||||
fields: z.array(z.custom<Field>()),
|
||||
})
|
||||
.nullable(),
|
||||
});
|
||||
|
||||
export type TGetEmbeddingDocumentRequestSchema = z.infer<typeof ZGetEmbeddingDocumentRequestSchema>;
|
||||
export type TGetEmbeddingDocumentResponseSchema = z.infer<
|
||||
typeof ZGetEmbeddingDocumentResponseSchema
|
||||
>;
|
||||
@ -0,0 +1,36 @@
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { verifyEmbeddingPresignToken } from '@documenso/lib/server-only/embedding-presign/verify-embedding-presign-token';
|
||||
|
||||
import { procedure } from '../trpc';
|
||||
import {
|
||||
ZVerifyEmbeddingPresignTokenRequestSchema,
|
||||
ZVerifyEmbeddingPresignTokenResponseSchema,
|
||||
verifyEmbeddingPresignTokenMeta,
|
||||
} from './verify-embedding-presign-token.types';
|
||||
|
||||
/**
|
||||
* Public route.
|
||||
*/
|
||||
export const verifyEmbeddingPresignTokenRoute = procedure
|
||||
.meta(verifyEmbeddingPresignTokenMeta)
|
||||
.input(ZVerifyEmbeddingPresignTokenRequestSchema)
|
||||
.output(ZVerifyEmbeddingPresignTokenResponseSchema)
|
||||
.mutation(async ({ input }) => {
|
||||
try {
|
||||
const { token } = input;
|
||||
|
||||
const apiToken = await verifyEmbeddingPresignToken({
|
||||
token,
|
||||
}).catch(() => null);
|
||||
|
||||
return { success: !!apiToken };
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new AppError(AppErrorCode.UNKNOWN_ERROR, {
|
||||
message: 'Failed to verify embedding presign token',
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,33 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import type { TrpcRouteMeta } from '../trpc';
|
||||
|
||||
export const verifyEmbeddingPresignTokenMeta: TrpcRouteMeta = {
|
||||
openapi: {
|
||||
method: 'POST',
|
||||
path: '/embedding/verify-presign-token',
|
||||
summary: 'Verify embedding presign token',
|
||||
description:
|
||||
'Verifies a presign token for embedding operations and returns the associated API token',
|
||||
tags: ['Embedding'],
|
||||
},
|
||||
};
|
||||
|
||||
export const ZVerifyEmbeddingPresignTokenRequestSchema = z.object({
|
||||
token: z
|
||||
.string()
|
||||
.min(1, { message: 'Token is required' })
|
||||
.describe('The presign token to verify'),
|
||||
});
|
||||
|
||||
export const ZVerifyEmbeddingPresignTokenResponseSchema = z.object({
|
||||
success: z.boolean(),
|
||||
});
|
||||
|
||||
export type TVerifyEmbeddingPresignTokenRequestSchema = z.infer<
|
||||
typeof ZVerifyEmbeddingPresignTokenRequestSchema
|
||||
>;
|
||||
|
||||
export type TVerifyEmbeddingPresignTokenResponseSchema = z.infer<
|
||||
typeof ZVerifyEmbeddingPresignTokenResponseSchema
|
||||
>;
|
||||
@ -2,6 +2,7 @@ import { adminRouter } from './admin-router/router';
|
||||
import { apiTokenRouter } from './api-token-router/router';
|
||||
import { authRouter } from './auth-router/router';
|
||||
import { documentRouter } from './document-router/router';
|
||||
import { embeddingPresignRouter } from './embedding-router/_router';
|
||||
import { fieldRouter } from './field-router/router';
|
||||
import { profileRouter } from './profile-router/router';
|
||||
import { recipientRouter } from './recipient-router/router';
|
||||
@ -23,6 +24,7 @@ export const appRouter = router({
|
||||
team: teamRouter,
|
||||
template: templateRouter,
|
||||
webhook: webhookRouter,
|
||||
embeddingPresign: embeddingPresignRouter,
|
||||
});
|
||||
|
||||
export type AppRouter = typeof appRouter;
|
||||
|
||||
Reference in New Issue
Block a user