feat: get many endpoints (#2226)

Co-authored-by: Lucas Smith <me@lucasjamessmith.me>
This commit is contained in:
Catalin Pit
2025-12-24 02:02:02 +02:00
committed by GitHub
parent aa1cada79b
commit 90fdba8000
12 changed files with 927 additions and 0 deletions
@@ -0,0 +1,65 @@
import { EnvelopeType } from '@prisma/client';
import { getMultipleEnvelopeWhereInput } from '@documenso/lib/server-only/envelope/get-envelopes-by-ids';
import { mapEnvelopesToDocumentMany } from '@documenso/lib/utils/document';
import { prisma } from '@documenso/prisma';
import { authenticatedProcedure } from '../trpc';
import {
ZGetDocumentsByIdsRequestSchema,
ZGetDocumentsByIdsResponseSchema,
getDocumentsByIdsMeta,
} from './get-documents-by-ids.types';
export const getDocumentsByIdsRoute = authenticatedProcedure
.meta(getDocumentsByIdsMeta)
.input(ZGetDocumentsByIdsRequestSchema)
.output(ZGetDocumentsByIdsResponseSchema)
.mutation(async ({ input, ctx }) => {
const { teamId, user } = ctx;
const { documentIds } = input;
ctx.logger.info({
input: {
documentIds,
},
});
const { envelopeWhereInput } = await getMultipleEnvelopeWhereInput({
ids: {
type: 'documentId',
ids: documentIds,
},
userId: user.id,
teamId,
type: EnvelopeType.DOCUMENT,
});
const envelopes = await prisma.envelope.findMany({
where: envelopeWhereInput,
include: {
user: {
select: {
id: true,
name: true,
email: true,
},
},
recipients: {
orderBy: {
id: 'asc',
},
},
team: {
select: {
id: true,
url: true,
},
},
},
});
return {
data: envelopes.map((envelope) => mapEnvelopesToDocumentMany(envelope)),
};
});
@@ -0,0 +1,26 @@
import { z } from 'zod';
import { ZDocumentManySchema } from '@documenso/lib/types/document';
import type { TrpcRouteMeta } from '../trpc';
export const getDocumentsByIdsMeta: TrpcRouteMeta = {
openapi: {
method: 'POST',
path: '/document/get-many',
summary: 'Get multiple documents',
description: 'Retrieve multiple documents by their IDs',
tags: ['Document'],
},
};
export const ZGetDocumentsByIdsRequestSchema = z.object({
documentIds: z.array(z.number()).min(1),
});
export const ZGetDocumentsByIdsResponseSchema = z.object({
data: z.array(ZDocumentManySchema),
});
export type TGetDocumentsByIdsRequest = z.infer<typeof ZGetDocumentsByIdsRequestSchema>;
export type TGetDocumentsByIdsResponse = z.infer<typeof ZGetDocumentsByIdsResponseSchema>;
@@ -19,6 +19,7 @@ import { findDocumentsInternalRoute } from './find-documents-internal';
import { findInboxRoute } from './find-inbox';
import { getDocumentRoute } from './get-document';
import { getDocumentByTokenRoute } from './get-document-by-token';
import { getDocumentsByIdsRoute } from './get-documents-by-ids';
import { getInboxCountRoute } from './get-inbox-count';
import { redistributeDocumentRoute } from './redistribute-document';
import { searchDocumentRoute } from './search-document';
@@ -27,6 +28,7 @@ import { updateDocumentRoute } from './update-document';
export const documentRouter = router({
get: getDocumentRoute,
getMany: getDocumentsByIdsRoute,
find: findDocumentsRoute,
create: createDocumentRoute,
update: updateDocumentRoute,
@@ -0,0 +1,34 @@
import { getEnvelopesByIds } from '@documenso/lib/server-only/envelope/get-envelopes-by-ids';
import { authenticatedProcedure } from '../trpc';
import {
ZGetEnvelopesByIdsRequestSchema,
ZGetEnvelopesByIdsResponseSchema,
getEnvelopesByIdsMeta,
} from './get-envelopes-by-ids.types';
export const getEnvelopesByIdsRoute = authenticatedProcedure
.meta(getEnvelopesByIdsMeta)
.input(ZGetEnvelopesByIdsRequestSchema)
.output(ZGetEnvelopesByIdsResponseSchema)
.mutation(async ({ input, ctx }) => {
const { teamId, user } = ctx;
const { ids } = input;
ctx.logger.info({
input: {
ids,
},
});
const envelopes = await getEnvelopesByIds({
ids,
userId: user.id,
teamId,
type: null,
});
return {
data: envelopes,
};
});
@@ -0,0 +1,41 @@
import { z } from 'zod';
import { ZEnvelopeSchema } from '@documenso/lib/types/envelope';
import type { TrpcRouteMeta } from '../trpc';
export const getEnvelopesByIdsMeta: TrpcRouteMeta = {
openapi: {
method: 'POST',
path: '/envelope/get-many',
summary: 'Get multiple envelopes',
description: 'Retrieve multiple envelopes by their IDs',
tags: ['Envelope'],
},
};
export const ZEnvelopeIdsSchema = z.discriminatedUnion('type', [
z.object({
type: z.literal('envelopeId'),
ids: z.array(z.string()).min(1).max(20),
}),
z.object({
type: z.literal('documentId'),
ids: z.array(z.number()).min(1).max(20),
}),
z.object({
type: z.literal('templateId'),
ids: z.array(z.number()).min(1).max(20),
}),
]);
export const ZGetEnvelopesByIdsRequestSchema = z.object({
ids: ZEnvelopeIdsSchema,
});
export const ZGetEnvelopesByIdsResponseSchema = z.object({
data: z.array(ZEnvelopeSchema),
});
export type TGetEnvelopesByIdsRequest = z.infer<typeof ZGetEnvelopesByIdsRequestSchema>;
export type TGetEnvelopesByIdsResponse = z.infer<typeof ZGetEnvelopesByIdsResponseSchema>;
@@ -23,6 +23,7 @@ import { findEnvelopeAuditLogsRoute } from './find-envelope-audit-logs';
import { getEnvelopeRoute } from './get-envelope';
import { getEnvelopeItemsRoute } from './get-envelope-items';
import { getEnvelopeItemsByTokenRoute } from './get-envelope-items-by-token';
import { getEnvelopesByIdsRoute } from './get-envelopes-by-ids';
import { redistributeEnvelopeRoute } from './redistribute-envelope';
import { setEnvelopeFieldsRoute } from './set-envelope-fields';
import { setEnvelopeRecipientsRoute } from './set-envelope-recipients';
@@ -72,6 +73,7 @@ export const envelopeRouter = router({
find: findEnvelopeAuditLogsRoute,
},
get: getEnvelopeRoute,
getMany: getEnvelopesByIdsRoute,
create: createEnvelopeRoute,
use: useEnvelopeRoute,
update: updateEnvelopeRoute,
@@ -0,0 +1,125 @@
import { EnvelopeType } from '@prisma/client';
import { getMultipleEnvelopeWhereInput } from '@documenso/lib/server-only/envelope/get-envelopes-by-ids';
import { mapSecondaryIdToTemplateId } from '@documenso/lib/utils/envelope';
import { mapFieldToLegacyField } from '@documenso/lib/utils/fields';
import { mapRecipientToLegacyRecipient } from '@documenso/lib/utils/recipients';
import { prisma } from '@documenso/prisma';
import { authenticatedProcedure } from '../trpc';
import {
ZGetTemplatesByIdsRequestSchema,
ZGetTemplatesByIdsResponseSchema,
getTemplatesByIdsMeta,
} from './get-templates-by-ids.types';
export const getTemplatesByIdsRoute = authenticatedProcedure
.meta(getTemplatesByIdsMeta)
.input(ZGetTemplatesByIdsRequestSchema)
.output(ZGetTemplatesByIdsResponseSchema)
.mutation(async ({ input, ctx }) => {
const { teamId, user } = ctx;
const { templateIds } = input;
ctx.logger.info({
input: {
templateIds,
},
});
const { envelopeWhereInput } = await getMultipleEnvelopeWhereInput({
ids: {
type: 'templateId',
ids: templateIds,
},
userId: user.id,
teamId,
type: EnvelopeType.TEMPLATE,
});
const envelopes = await prisma.envelope.findMany({
where: envelopeWhereInput,
include: {
recipients: {
orderBy: {
id: 'asc',
},
},
envelopeItems: {
select: {
documentData: true,
},
},
fields: true,
team: {
select: {
id: true,
url: true,
},
},
documentMeta: {
select: {
signingOrder: true,
distributionMethod: true,
},
},
directLink: {
select: {
token: true,
enabled: true,
},
},
},
});
const templates = envelopes.map((envelope) => {
const legacyTemplateId = mapSecondaryIdToTemplateId(envelope.secondaryId);
const firstTemplateDocumentData = envelope.envelopeItems[0].documentData;
return {
id: legacyTemplateId,
envelopeId: envelope.id,
type: envelope.templateType,
visibility: envelope.visibility,
externalId: envelope.externalId,
title: envelope.title,
userId: envelope.userId,
teamId: envelope.teamId,
authOptions: envelope.authOptions,
createdAt: envelope.createdAt,
updatedAt: envelope.updatedAt,
publicTitle: envelope.publicTitle,
publicDescription: envelope.publicDescription,
folderId: envelope.folderId,
useLegacyFieldInsertion: envelope.useLegacyFieldInsertion,
team: envelope.team
? {
id: envelope.team.id,
url: envelope.team.url,
}
: null,
fields: envelope.fields.map((field) => mapFieldToLegacyField(field, envelope)),
recipients: envelope.recipients.map((recipient) =>
mapRecipientToLegacyRecipient(recipient, envelope),
),
templateMeta: envelope.documentMeta
? {
signingOrder: envelope.documentMeta.signingOrder,
distributionMethod: envelope.documentMeta.distributionMethod,
}
: null,
directLink: envelope.directLink
? {
token: envelope.directLink.token,
enabled: envelope.directLink.enabled,
}
: null,
templateDocumentDataId: firstTemplateDocumentData.id, // Backwards compatibility.
};
});
return {
data: templates,
};
});
@@ -0,0 +1,26 @@
import { z } from 'zod';
import { ZTemplateManySchema } from '@documenso/lib/types/template';
import type { TrpcRouteMeta } from '../trpc';
export const getTemplatesByIdsMeta: TrpcRouteMeta = {
openapi: {
method: 'POST',
path: '/template/get-many',
summary: 'Get multiple templates',
description: 'Retrieve multiple templates by their IDs',
tags: ['Template'],
},
};
export const ZGetTemplatesByIdsRequestSchema = z.object({
templateIds: z.array(z.number()).min(1),
});
export const ZGetTemplatesByIdsResponseSchema = z.object({
data: z.array(ZTemplateManySchema),
});
export type TGetTemplatesByIdsRequest = z.infer<typeof ZGetTemplatesByIdsRequestSchema>;
export type TGetTemplatesByIdsResponse = z.infer<typeof ZGetTemplatesByIdsResponseSchema>;
@@ -30,6 +30,7 @@ import { mapEnvelopeToTemplateLite } from '@documenso/lib/utils/templates';
import { ZGenericSuccessResponse, ZSuccessResponseSchema } from '../schema';
import { authenticatedProcedure, maybeAuthenticatedProcedure, router } from '../trpc';
import { getTemplatesByIdsRoute } from './get-templates-by-ids';
import {
ZBulkSendTemplateMutationSchema,
ZCreateDocumentFromDirectTemplateRequestSchema,
@@ -154,6 +155,11 @@ export const templateRouter = router({
});
}),
/**
* @public
*/
getMany: getTemplatesByIdsRoute,
/**
* Wait until RR7 so we can passthrough documents.
*