fix: refactor routers (#1523)

This commit is contained in:
David Nguyen
2024-12-10 16:11:20 +09:00
committed by GitHub
parent dd162205fa
commit fae9c0ca24
33 changed files with 1122 additions and 738 deletions

View File

@ -1,5 +1,6 @@
import { TRPCError } from '@trpc/server';
import { DateTime } from 'luxon';
import { z } from 'zod';
import { getServerLimits } from '@documenso/ee/server-only/limits/server';
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
@ -28,7 +29,7 @@ import { DocumentStatus } from '@documenso/prisma/client';
import { authenticatedProcedure, procedure, router } from '../trpc';
import {
ZCreateDocumentMutationSchema,
ZDeleteDraftDocumentMutationSchema as ZDeleteDocumentMutationSchema,
ZDeleteDocumentMutationSchema,
ZDownloadAuditLogsMutationSchema,
ZDownloadCertificateMutationSchema,
ZFindDocumentAuditLogsQuerySchema,
@ -48,6 +49,7 @@ import {
} from './schema';
export const documentRouter = router({
// Internal endpoint for now.
getDocumentById: authenticatedProcedure
.input(ZGetDocumentByIdQuerySchema)
.query(async ({ input, ctx }) => {
@ -57,6 +59,7 @@ export const documentRouter = router({
});
}),
// Internal endpoint for now.
getDocumentByToken: procedure
.input(ZGetDocumentByTokenQuerySchema)
.query(async ({ input, ctx }) => {
@ -68,8 +71,50 @@ export const documentRouter = router({
});
}),
findDocuments: authenticatedProcedure
.meta({
openapi: {
method: 'GET',
path: '/document/find',
summary: 'Find documents',
description: 'Find documents based on a search criteria',
tags: ['Documents'],
},
})
.input(ZFindDocumentsQuerySchema)
.output(z.unknown())
.query(async ({ input, ctx }) => {
const { user } = ctx;
const { search, teamId, templateId, page, perPage, orderBy, source, status } = input;
const documents = await findDocuments({
userId: user.id,
teamId,
templateId,
search,
source,
status,
page,
perPage,
orderBy,
});
return documents;
}),
getDocumentWithDetailsById: authenticatedProcedure
.meta({
openapi: {
method: 'GET',
path: '/document/{documentId}',
summary: 'Get document',
description: 'Returns a document given an ID',
tags: ['Documents'],
},
})
.input(ZGetDocumentWithDetailsByIdQuerySchema)
.output(z.unknown())
.query(async ({ input, ctx }) => {
return await getDocumentWithDetailsById({
...input,
@ -78,7 +123,16 @@ export const documentRouter = router({
}),
createDocument: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/document/create',
summary: 'Create document',
tags: ['Documents'],
},
})
.input(ZCreateDocumentMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { title, documentDataId, teamId } = input;
@ -100,76 +154,18 @@ export const documentRouter = router({
});
}),
deleteDocument: authenticatedProcedure
.input(ZDeleteDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {
const { id, teamId } = input;
const userId = ctx.user.id;
return await deleteDocument({
id,
userId,
teamId,
requestMetadata: extractNextApiRequestMetadata(ctx.req),
});
}),
moveDocumentToTeam: authenticatedProcedure
.input(ZMoveDocumentsToTeamSchema)
.mutation(async ({ input, ctx }) => {
const { documentId, teamId } = input;
const userId = ctx.user.id;
return await moveDocumentToTeam({
documentId,
teamId,
userId,
requestMetadata: extractNextApiRequestMetadata(ctx.req),
});
}),
findDocuments: authenticatedProcedure
.input(ZFindDocumentsQuerySchema)
.query(async ({ input, ctx }) => {
const { user } = ctx;
const { search, teamId, templateId, page, perPage, orderBy, source, status } = input;
const documents = await findDocuments({
userId: user.id,
teamId,
templateId,
search,
source,
status,
page,
perPage,
orderBy,
});
return documents;
}),
findDocumentAuditLogs: authenticatedProcedure
.input(ZFindDocumentAuditLogsQuerySchema)
.query(async ({ input, ctx }) => {
const { page, perPage, documentId, cursor, filterForRecentActivity, orderBy } = input;
return await findDocumentAuditLogs({
page,
perPage,
documentId,
cursor,
filterForRecentActivity,
orderBy,
userId: ctx.user.id,
});
}),
// Todo: Add API
// Todo: Refactor to updateDocument.
setSettingsForDocument: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/document/{documentId}',
summary: 'Update document',
tags: ['Documents'],
},
})
.input(ZSetSettingsForDocumentMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { documentId, teamId, data, meta } = input;
@ -198,6 +194,56 @@ export const documentRouter = router({
});
}),
deleteDocument: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/document/{documentId}/delete',
summary: 'Delete document',
tags: ['Documents'],
},
})
.input(ZDeleteDocumentMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { documentId, teamId } = input;
const userId = ctx.user.id;
return await deleteDocument({
id: documentId,
userId,
teamId,
requestMetadata: extractNextApiRequestMetadata(ctx.req),
});
}),
moveDocumentToTeam: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/document/{documentId}/move',
summary: 'Move document',
description: 'Move a document to a team',
tags: ['Documents'],
},
})
.input(ZMoveDocumentsToTeamSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { documentId, teamId } = input;
const userId = ctx.user.id;
return await moveDocumentToTeam({
documentId,
teamId,
userId,
requestMetadata: extractNextApiRequestMetadata(ctx.req),
});
}),
// Internal endpoint for now.
// Should probably use `updateDocument`
setTitleForDocument: authenticatedProcedure
.input(ZSetTitleForDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {
@ -214,6 +260,7 @@ export const documentRouter = router({
});
}),
// Internal endpoint for now.
setPasswordForDocument: authenticatedProcedure
.input(ZSetPasswordForDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {
@ -238,6 +285,7 @@ export const documentRouter = router({
});
}),
// Internal endpoint for now.
setSigningOrderForDocument: authenticatedProcedure
.input(ZSetSigningOrderForDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {
@ -251,13 +299,14 @@ export const documentRouter = router({
});
}),
// Internal endpoint for now.
updateTypedSignatureSettings: authenticatedProcedure
.input(ZUpdateTypedSignatureSettingsMutationSchema)
.mutation(async ({ input, ctx }) => {
const { documentId, teamId, typedSignatureEnabled } = input;
const document = await getDocumentById({
id: documentId,
documentId,
teamId,
userId: ctx.user.id,
}).catch(() => null);
@ -277,8 +326,20 @@ export const documentRouter = router({
});
}),
// Todo: Refactor to distributeDocument.
// Todo: Rework before releasing API.
sendDocument: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/document/{documentId}/distribute',
summary: 'Distribute document',
description: 'Send the document out to recipients based on your distribution method',
tags: ['Documents'],
},
})
.input(ZSendDocumentMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { documentId, teamId, meta } = input;
@ -314,7 +375,18 @@ export const documentRouter = router({
}),
resendDocument: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/document/{documentId}/resend',
summary: 'Resend document',
description:
'Resend the document to recipients who have not signed. Will use the distribution method set in the document.',
tags: ['Documents'],
},
})
.input(ZResendDocumentMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
return await resendDocument({
userId: ctx.user.id,
@ -324,7 +396,16 @@ export const documentRouter = router({
}),
duplicateDocument: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/document/{documentId}/duplicate',
summary: 'Duplicate document',
tags: ['Documents'],
},
})
.input(ZGetDocumentByIdQuerySchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
return await duplicateDocumentById({
userId: ctx.user.id,
@ -332,6 +413,7 @@ export const documentRouter = router({
});
}),
// Internal endpoint for now.
searchDocuments: authenticatedProcedure
.input(ZSearchDocumentsMutationSchema)
.query(async ({ input, ctx }) => {
@ -345,13 +427,31 @@ export const documentRouter = router({
return documents;
}),
// Internal endpoint for now.
findDocumentAuditLogs: authenticatedProcedure
.input(ZFindDocumentAuditLogsQuerySchema)
.query(async ({ input, ctx }) => {
const { page, perPage, documentId, cursor, filterForRecentActivity, orderBy } = input;
return await findDocumentAuditLogs({
page,
perPage,
documentId,
cursor,
filterForRecentActivity,
orderBy,
userId: ctx.user.id,
});
}),
// Internal endpoint for now.
downloadAuditLogs: authenticatedProcedure
.input(ZDownloadAuditLogsMutationSchema)
.mutation(async ({ input, ctx }) => {
const { documentId, teamId } = input;
const document = await getDocumentById({
id: documentId,
documentId,
userId: ctx.user.id,
teamId,
}).catch(() => null);
@ -373,13 +473,14 @@ export const documentRouter = router({
};
}),
// Internal endpoint for now.
downloadCertificate: authenticatedProcedure
.input(ZDownloadCertificateMutationSchema)
.mutation(async ({ input, ctx }) => {
const { documentId, teamId } = input;
const document = await getDocumentById({
id: documentId,
documentId,
userId: ctx.user.id,
teamId,
});

View File

@ -48,7 +48,7 @@ export const ZFindDocumentAuditLogsQuerySchema = ZBaseTableSearchParamsSchema.ex
});
export const ZGetDocumentByIdQuerySchema = z.object({
id: z.number().min(1),
documentId: z.number().min(1),
teamId: z.number().min(1).optional(),
});
@ -61,7 +61,7 @@ export const ZGetDocumentByTokenQuerySchema = z.object({
export type TGetDocumentByTokenQuerySchema = z.infer<typeof ZGetDocumentByTokenQuerySchema>;
export const ZGetDocumentWithDetailsByIdQuerySchema = z.object({
id: z.number().min(1),
documentId: z.number().min(1),
teamId: z.number().min(1).optional(),
});
@ -206,12 +206,12 @@ export const ZResendDocumentMutationSchema = z.object({
export type TSendDocumentMutationSchema = z.infer<typeof ZSendDocumentMutationSchema>;
export const ZDeleteDraftDocumentMutationSchema = z.object({
id: z.number().min(1),
export const ZDeleteDocumentMutationSchema = z.object({
documentId: z.number().min(1),
teamId: z.number().min(1).optional(),
});
export type TDeleteDraftDocumentMutationSchema = z.infer<typeof ZDeleteDraftDocumentMutationSchema>;
export type TDeleteDocumentMutationSchema = z.infer<typeof ZDeleteDocumentMutationSchema>;
export const ZSearchDocumentsMutationSchema = z.object({
query: z.string(),

View File

@ -1,3 +1,5 @@
import { z } from 'zod';
import { getFieldById } from '@documenso/lib/server-only/field/get-field-by-id';
import { removeSignedFieldWithToken } from '@documenso/lib/server-only/field/remove-signed-field-with-token';
import { setFieldsForDocument } from '@documenso/lib/server-only/field/set-fields-for-document';
@ -15,8 +17,39 @@ import {
} from './schema';
export const fieldRouter = router({
getField: authenticatedProcedure
.meta({
openapi: {
method: 'GET',
path: '/field/{fieldId}',
summary: 'Get field',
description: 'Returns a document or template field',
tags: ['Fields'],
},
})
.input(ZGetFieldQuerySchema)
.output(z.unknown())
.query(async ({ input, ctx }) => {
const { fieldId, teamId } = input;
return await getFieldById({
userId: ctx.user.id,
teamId,
fieldId,
});
}),
addFields: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/document/{documentId}/field',
summary: 'Set document fields',
tags: ['Fields'],
},
})
.input(ZAddFieldsMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { documentId, fields } = input;
@ -39,7 +72,16 @@ export const fieldRouter = router({
}),
addTemplateFields: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/template/{templateId}/field',
summary: 'Set template fields',
tags: ['Fields'],
},
})
.input(ZAddTemplateFieldsMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { templateId, fields } = input;
@ -60,6 +102,7 @@ export const fieldRouter = router({
});
}),
// Internal endpoint for now.
signFieldWithToken: procedure
.input(ZSignFieldWithTokenMutationSchema)
.mutation(async ({ input, ctx }) => {
@ -76,6 +119,7 @@ export const fieldRouter = router({
});
}),
// Internal endpoint for now.
removeSignedFieldWithToken: procedure
.input(ZRemovedSignedFieldWithTokenMutationSchema)
.mutation(async ({ input, ctx }) => {
@ -87,40 +131,4 @@ export const fieldRouter = router({
requestMetadata: extractNextApiRequestMetadata(ctx.req),
});
}),
getField: authenticatedProcedure.input(ZGetFieldQuerySchema).query(async ({ input, ctx }) => {
const { fieldId, teamId } = input;
return await getFieldById({
userId: ctx.user.id,
teamId,
fieldId,
});
}),
// This doesn't appear to be used anywhere, and it doesn't seem to support updating template fields
// so commenting this out for now.
// updateField: authenticatedProcedure
// .input(ZUpdateFieldMutationSchema)
// .mutation(async ({ input, ctx }) => {
// try {
// const { documentId, fieldId, fieldMeta, teamId } = input;
// return await updateField({
// userId: ctx.user.id,
// teamId,
// fieldId,
// documentId,
// requestMetadata: extractNextApiRequestMetadata(ctx.req),
// fieldMeta: fieldMeta,
// });
// } catch (err) {
// console.error(err);
// throw new TRPCError({
// code: 'BAD_REQUEST',
// message: 'We were unable to set this field. Please try again later.',
// });
// }
// }),
});

View File

@ -1,3 +1,5 @@
import { z } from 'zod';
import { completeDocumentWithToken } from '@documenso/lib/server-only/document/complete-document-with-token';
import { rejectDocumentWithToken } from '@documenso/lib/server-only/document/reject-document-with-token';
import { setRecipientsForDocument } from '@documenso/lib/server-only/recipient/set-recipients-for-document';
@ -14,7 +16,16 @@ import {
export const recipientRouter = router({
addSigners: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/document/{documentId}/recipient/set',
summary: 'Set document recipients',
tags: ['Recipients'],
},
})
.input(ZAddSignersMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { documentId, teamId, signers } = input;
@ -35,7 +46,16 @@ export const recipientRouter = router({
}),
addTemplateSigners: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/template/{templateId}/recipient/set',
summary: 'Set template recipients',
tags: ['Recipients'],
},
})
.input(ZAddTemplateSignersMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { templateId, signers, teamId } = input;
@ -54,6 +74,7 @@ export const recipientRouter = router({
});
}),
// Internal endpoint for now.
completeDocumentWithToken: procedure
.input(ZCompleteDocumentWithTokenMutationSchema)
.mutation(async ({ input, ctx }) => {
@ -68,6 +89,7 @@ export const recipientRouter = router({
});
}),
// Internal endpoint for now.
rejectDocumentWithToken: procedure
.input(ZRejectDocumentWithTokenMutationSchema)
.mutation(async ({ input, ctx }) => {

View File

@ -4,7 +4,7 @@ import { z } from 'zod';
import { getTeamPrices } from '@documenso/ee/server-only/stripe/get-team-prices';
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
import { acceptTeamInvitation } from '@documenso/lib/server-only/team/accept-team-invitation';
import { ZCreateTeamResponseSchema, createTeam } from '@documenso/lib/server-only/team/create-team';
import { createTeam } from '@documenso/lib/server-only/team/create-team';
import { createTeamBillingPortal } from '@documenso/lib/server-only/team/create-team-billing-portal';
import { createTeamPendingCheckoutSession } from '@documenso/lib/server-only/team/create-team-checkout-session';
import { createTeamEmailVerification } from '@documenso/lib/server-only/team/create-team-email-verification';
@ -18,43 +18,22 @@ import { deleteTeamMembers } from '@documenso/lib/server-only/team/delete-team-m
import { deleteTeamPending } from '@documenso/lib/server-only/team/delete-team-pending';
import { deleteTeamTransferRequest } from '@documenso/lib/server-only/team/delete-team-transfer-request';
import { findTeamInvoices } from '@documenso/lib/server-only/team/find-team-invoices';
import {
ZFindTeamMemberInvitesResponseSchema,
findTeamMemberInvites,
} from '@documenso/lib/server-only/team/find-team-member-invites';
import {
ZFindTeamMembersResponseSchema,
findTeamMembers,
} from '@documenso/lib/server-only/team/find-team-members';
import { findTeamMemberInvites } from '@documenso/lib/server-only/team/find-team-member-invites';
import { findTeamMembers } from '@documenso/lib/server-only/team/find-team-members';
import { findTeams } from '@documenso/lib/server-only/team/find-teams';
import {
ZFindTeamsPendingResponseSchema,
findTeamsPending,
} from '@documenso/lib/server-only/team/find-teams-pending';
import { ZGetTeamByIdResponseSchema, getTeamById } from '@documenso/lib/server-only/team/get-team';
import { findTeamsPending } from '@documenso/lib/server-only/team/find-teams-pending';
import { getTeamById } from '@documenso/lib/server-only/team/get-team';
import { getTeamEmailByEmail } from '@documenso/lib/server-only/team/get-team-email-by-email';
import {
ZGetTeamInvitationsResponseSchema,
getTeamInvitations,
} from '@documenso/lib/server-only/team/get-team-invitations';
import {
ZGetTeamMembersResponseSchema,
getTeamMembers,
} from '@documenso/lib/server-only/team/get-team-members';
import { ZGetTeamsResponseSchema, getTeams } from '@documenso/lib/server-only/team/get-teams';
import { getTeamInvitations } from '@documenso/lib/server-only/team/get-team-invitations';
import { getTeamMembers } from '@documenso/lib/server-only/team/get-team-members';
import { getTeams } from '@documenso/lib/server-only/team/get-teams';
import { leaveTeam } from '@documenso/lib/server-only/team/leave-team';
import { requestTeamOwnershipTransfer } from '@documenso/lib/server-only/team/request-team-ownership-transfer';
import { resendTeamEmailVerification } from '@documenso/lib/server-only/team/resend-team-email-verification';
import { resendTeamMemberInvitation } from '@documenso/lib/server-only/team/resend-team-member-invitation';
import { updateTeam } from '@documenso/lib/server-only/team/update-team';
import {
ZUpdateTeamBrandingSettingsResponseSchema,
updateTeamBrandingSettings,
} from '@documenso/lib/server-only/team/update-team-branding-settings';
import {
ZUpdateTeamDocumentSettingsResponseSchema,
updateTeamDocumentSettings,
} from '@documenso/lib/server-only/team/update-team-document-settings';
import { updateTeamBrandingSettings } from '@documenso/lib/server-only/team/update-team-branding-settings';
import { updateTeamDocumentSettings } from '@documenso/lib/server-only/team/update-team-document-settings';
import { updateTeamEmail } from '@documenso/lib/server-only/team/update-team-email';
import { updateTeamMember } from '@documenso/lib/server-only/team/update-team-member';
import { updateTeamPublicProfile } from '@documenso/lib/server-only/team/update-team-public-profile';
@ -95,6 +74,516 @@ import {
} from './schema';
export const teamRouter = router({
getTeams: authenticatedProcedure
.meta({
openapi: {
method: 'GET',
path: '/team',
summary: 'Get teams',
description: 'Returns all teams that you are a member of',
tags: ['Teams'],
},
})
.input(z.void())
.output(z.unknown())
.query(async ({ ctx }) => {
return await getTeams({ userId: ctx.user.id });
}),
getTeam: authenticatedProcedure
.meta({
openapi: {
method: 'GET',
path: '/team/{teamId}',
summary: 'Get team',
tags: ['Teams'],
},
})
.input(ZGetTeamQuerySchema)
.output(z.unknown())
.query(async ({ input, ctx }) => {
return await getTeamById({ teamId: input.teamId, userId: ctx.user.id });
}),
createTeam: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/team/create',
summary: 'Create team',
tags: ['Teams'],
},
})
.input(ZCreateTeamMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
return await createTeam({
userId: ctx.user.id,
...input,
});
}),
updateTeam: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/team/{teamId}',
summary: 'Update team',
tags: ['Teams'],
},
})
.input(ZUpdateTeamMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
return await updateTeam({
userId: ctx.user.id,
...input,
});
}),
deleteTeam: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/team/{teamId}/delete',
summary: 'Delete team',
tags: ['Teams'],
},
})
.input(ZDeleteTeamMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
return await deleteTeam({
userId: ctx.user.id,
...input,
});
}),
leaveTeam: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/team/{teamId}/leave',
summary: 'Leave a team',
description: '',
tags: ['Teams'],
},
})
.input(ZLeaveTeamMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
return await leaveTeam({
userId: ctx.user.id,
...input,
});
}),
findTeamMemberInvites: authenticatedProcedure
.meta({
openapi: {
method: 'GET',
path: '/team/{teamId}/member/invite',
summary: 'Find member invites',
description: 'Returns pending team member invites',
tags: ['Teams'],
},
})
.input(ZFindTeamMemberInvitesQuerySchema)
.output(z.unknown())
.query(async ({ input, ctx }) => {
return await findTeamMemberInvites({
userId: ctx.user.id,
...input,
});
}),
createTeamMemberInvites: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/team/{teamId}/member/invite',
summary: 'Invite members',
description: 'Send email invitations to users to join the team',
tags: ['Teams'],
},
})
.input(ZCreateTeamMemberInvitesMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
return await createTeamMemberInvites({
userId: ctx.user.id,
userName: ctx.user.name ?? '',
...input,
});
}),
resendTeamMemberInvitation: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/team/{teamId}/member/invite/{invitationId}/resend',
summary: 'Resend member invite',
description: 'Resend an email invitation to a user to join the team',
tags: ['Teams'],
},
})
.input(ZResendTeamMemberInvitationMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
await resendTeamMemberInvitation({
userId: ctx.user.id,
userName: ctx.user.name ?? '',
...input,
});
}),
deleteTeamMemberInvitations: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/team/{teamId}/member/invite/delete',
summary: 'Delete member invite',
description: 'Delete a pending team member invite',
tags: ['Teams'],
},
})
.input(ZDeleteTeamMemberInvitationsMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
return await deleteTeamMemberInvitations({
userId: ctx.user.id,
...input,
});
}),
getTeamMembers: authenticatedProcedure
.meta({
openapi: {
method: 'GET',
path: '/team/{teamId}/member',
summary: 'Get members',
tags: ['Teams'],
},
})
.input(ZGetTeamMembersQuerySchema)
.output(z.unknown())
.query(async ({ input, ctx }) => {
return await getTeamMembers({ teamId: input.teamId, userId: ctx.user.id });
}),
findTeamMembers: authenticatedProcedure
.meta({
openapi: {
method: 'GET',
path: '/team/{teamId}/member/find',
summary: 'Find members',
description: 'Find team members based on a search criteria',
tags: ['Teams'],
},
})
.input(ZFindTeamMembersQuerySchema)
.output(z.unknown())
.query(async ({ input, ctx }) => {
return await findTeamMembers({
userId: ctx.user.id,
...input,
});
}),
updateTeamMember: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/team/{teamId}/member/{teamMemberId}',
summary: 'Update member',
tags: ['Teams'],
},
})
.input(ZUpdateTeamMemberMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
return await updateTeamMember({
userId: ctx.user.id,
...input,
});
}),
deleteTeamMembers: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/team/{teamId}/member/delete',
summary: 'Delete members',
description: '',
tags: ['Teams'],
},
})
.input(ZDeleteTeamMembersMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
return await deleteTeamMembers({
userId: ctx.user.id,
...input,
});
}),
// Todo: Refactor, seems to be a redundant endpoint.
findTeams: authenticatedProcedure.input(ZFindTeamsQuerySchema).query(async ({ input, ctx }) => {
return await findTeams({
userId: ctx.user.id,
...input,
});
}),
// Internal endpoint for now.
createTeamEmailVerification: authenticatedProcedure
// .meta({
// openapi: {
// method: 'POST',
// path: '/team/{teamId}/email/create',
// summary: 'Create team email',
// description: 'Add an email to a team and send an email request to verify it',
// tags: ['Teams'],
// },
// })
.input(ZCreateTeamEmailVerificationMutationSchema)
.mutation(async ({ input, ctx }) => {
return await createTeamEmailVerification({
teamId: input.teamId,
userId: ctx.user.id,
data: {
email: input.email,
name: input.name,
},
});
}),
// Internal endpoint for now.
getTeamInvitations: authenticatedProcedure
// .meta({
// openapi: {
// method: 'GET',
// path: '/team/invite',
// summary: 'Get team invitations',
// description: '',
// tags: ['Teams'],
// },
// })
.input(z.void())
.query(async ({ ctx }) => {
return await getTeamInvitations({ email: ctx.user.email });
}),
updateTeamPublicProfile: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/team/{teamId}/profile',
summary: 'Update a team public profile',
description: '',
tags: ['Teams'],
},
})
.input(ZUpdateTeamPublicProfileMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
try {
const { teamId, bio, enabled } = input;
await updateTeamPublicProfile({
userId: ctx.user.id,
teamId,
data: {
bio,
enabled,
},
});
} catch (err) {
console.error(err);
const error = AppError.parseError(err);
if (error.code !== AppErrorCode.UNKNOWN_ERROR) {
throw error;
}
throw new TRPCError({
code: 'BAD_REQUEST',
message:
'We were unable to update your public profile. Please review the information you provided and try again.',
});
}
}),
// Internal endpoint for now.
requestTeamOwnershipTransfer: authenticatedProcedure
// .meta({
// openapi: {
// method: 'POST',
// path: '/team/{teamId}/transfer',
// summary: 'Request a team ownership transfer',
// description: '',
// tags: ['Teams'],
// },
// })
.input(ZRequestTeamOwnerhsipTransferMutationSchema)
.mutation(async ({ input, ctx }) => {
return await requestTeamOwnershipTransfer({
userId: ctx.user.id,
userName: ctx.user.name ?? '',
...input,
});
}),
// Internal endpoint for now.
deleteTeamTransferRequest: authenticatedProcedure
// .meta({
// openapi: {
// method: 'POST',
// path: '/team/{teamId}/transfer/delete',
// summary: 'Delete team transfer request',
// tags: ['Teams'],
// },
// })
.input(ZDeleteTeamTransferRequestMutationSchema)
.mutation(async ({ input, ctx }) => {
return await deleteTeamTransferRequest({
userId: ctx.user.id,
...input,
});
}),
// Todo
getTeamEmailByEmail: authenticatedProcedure.query(async ({ ctx }) => {
return await getTeamEmailByEmail({ email: ctx.user.email });
}),
// Internal endpoint for now.
updateTeamEmail: authenticatedProcedure
// .meta({
// openapi: {
// method: 'POST',
// path: '/team/{teamId}/email',
// summary: 'Update a team email',
// description: '',
// tags: ['Teams'],
// },
// })
.input(ZUpdateTeamEmailMutationSchema)
.mutation(async ({ input, ctx }) => {
return await updateTeamEmail({
userId: ctx.user.id,
...input,
});
}),
// Internal endpoint for now.
deleteTeamEmail: authenticatedProcedure
// .meta({
// openapi: {
// method: 'POST',
// path: '/team/{teamId}/email/delete',
// summary: 'Delete team email',
// description: '',
// tags: ['Teams'],
// },
// })
.input(ZDeleteTeamEmailMutationSchema)
.mutation(async ({ input, ctx }) => {
return await deleteTeamEmail({
userId: ctx.user.id,
userEmail: ctx.user.email,
...input,
});
}),
// Internal endpoint for now.
resendTeamEmailVerification: authenticatedProcedure
// .meta({
// openapi: {
// method: 'POST',
// path: '/team/{teamId}/email/resend',
// summary: 'Resend team email verification',
// tags: ['Teams'],
// },
// })
.input(ZResendTeamEmailVerificationMutationSchema)
.mutation(async ({ input, ctx }) => {
await resendTeamEmailVerification({
userId: ctx.user.id,
...input,
});
}),
// Internal endpoint for now.
deleteTeamEmailVerification: authenticatedProcedure
// .meta({
// openapi: {
// method: 'POST',
// path: '/team/{teamId}/email/verify/delete',
// summary: 'Delete team email verification',
// tags: ['Teams'],
// },
// })
.input(ZDeleteTeamEmailVerificationMutationSchema)
.mutation(async ({ input, ctx }) => {
return await deleteTeamEmailVerification({
userId: ctx.user.id,
...input,
});
}),
// Internal endpoint. Use updateTeam instead.
updateTeamBrandingSettings: authenticatedProcedure
.input(ZUpdateTeamBrandingSettingsMutationSchema)
.mutation(async ({ ctx, input }) => {
const { teamId, settings } = input;
return await updateTeamBrandingSettings({
userId: ctx.user.id,
teamId,
settings,
});
}),
// Internal endpoint for now.
createTeamPendingCheckout: authenticatedProcedure
.input(ZCreateTeamPendingCheckoutMutationSchema)
.mutation(async ({ input, ctx }) => {
return await createTeamPendingCheckoutSession({
userId: ctx.user.id,
...input,
});
}),
// Internal endpoint for now.
findTeamInvoices: authenticatedProcedure
.input(ZFindTeamInvoicesQuerySchema)
.query(async ({ input, ctx }) => {
return await findTeamInvoices({
userId: ctx.user.id,
...input,
});
}),
// Internal endpoint for now.
getTeamPrices: authenticatedProcedure.query(async () => {
return await getTeamPrices();
}),
// Internal endpoint. Use updateTeam instead.
updateTeamDocumentSettings: authenticatedProcedure
.input(ZUpdateTeamDocumentSettingsMutationSchema)
.mutation(async ({ ctx, input }) => {
const { teamId, settings } = input;
return await updateTeamDocumentSettings({
userId: ctx.user.id,
teamId,
settings,
});
}),
// Internal endpoint for now.
acceptTeamInvitation: authenticatedProcedure
.input(ZAcceptTeamInvitationMutationSchema)
@ -125,169 +614,18 @@ export const teamRouter = router({
});
}),
createTeam: authenticatedProcedure
.meta({ openapi: { method: 'POST', path: '/team' } })
.input(ZCreateTeamMutationSchema)
.output(ZCreateTeamResponseSchema)
.mutation(async ({ input, ctx }) => {
return await createTeam({
userId: ctx.user.id,
...input,
});
}),
createTeamEmailVerification: authenticatedProcedure
.meta({ openapi: { method: 'POST', path: '/team/{teamId}/email' } })
.input(ZCreateTeamEmailVerificationMutationSchema)
.output(z.void())
.mutation(async ({ input, ctx }) => {
return await createTeamEmailVerification({
teamId: input.teamId,
userId: ctx.user.id,
data: {
email: input.email,
name: input.name,
},
});
}),
createTeamMemberInvites: authenticatedProcedure
.meta({ openapi: { method: 'POST', path: '/team/{teamId}/member/invite' } })
.input(ZCreateTeamMemberInvitesMutationSchema)
.output(z.void())
.mutation(async ({ input, ctx }) => {
return await createTeamMemberInvites({
userId: ctx.user.id,
userName: ctx.user.name ?? '',
...input,
});
}),
// Internal endpoint for now.
createTeamPendingCheckout: authenticatedProcedure
.input(ZCreateTeamPendingCheckoutMutationSchema)
.mutation(async ({ input, ctx }) => {
return await createTeamPendingCheckoutSession({
userId: ctx.user.id,
...input,
});
}),
deleteTeam: authenticatedProcedure
// .meta({ openapi: { method: 'DELETE', path: '/team/{teamId}' } })
.input(ZDeleteTeamMutationSchema)
.mutation(async ({ input, ctx }) => {
return await deleteTeam({
userId: ctx.user.id,
...input,
});
}),
deleteTeamEmail: authenticatedProcedure
// .meta({ openapi: { method: 'DELETE', path: '/team/{teamId}/email' } })
.input(ZDeleteTeamEmailMutationSchema)
.mutation(async ({ input, ctx }) => {
return await deleteTeamEmail({
userId: ctx.user.id,
userEmail: ctx.user.email,
...input,
});
}),
deleteTeamEmailVerification: authenticatedProcedure
// .meta({ openapi: { method: 'DELETE', path: '/team/{teamId}/email-verification' } })
.input(ZDeleteTeamEmailVerificationMutationSchema)
.mutation(async ({ input, ctx }) => {
return await deleteTeamEmailVerification({
userId: ctx.user.id,
...input,
});
}),
deleteTeamMemberInvitations: authenticatedProcedure
// .meta({ openapi: { method: 'DELETE', path: '/team/{teamId}/member/invite' } })
.input(ZDeleteTeamMemberInvitationsMutationSchema)
.mutation(async ({ input, ctx }) => {
return await deleteTeamMemberInvitations({
userId: ctx.user.id,
...input,
});
}),
deleteTeamMembers: authenticatedProcedure
// .meta({ openapi: { method: 'DELETE', path: '/team/{teamId}/member' } })
.input(ZDeleteTeamMembersMutationSchema)
.mutation(async ({ input, ctx }) => {
return await deleteTeamMembers({
userId: ctx.user.id,
...input,
});
}),
deleteTeamPending: authenticatedProcedure
// .meta({ openapi: { method: 'DELETE', path: '/team-pending/{pendingTeamId}' } })
.input(ZDeleteTeamPendingMutationSchema)
.mutation(async ({ input, ctx }) => {
return await deleteTeamPending({
userId: ctx.user.id,
...input,
});
}),
deleteTeamTransferRequest: authenticatedProcedure
// .meta({ openapi: { method: 'DELETE', path: '/team/{teamId}/transfer' } })
.input(ZDeleteTeamTransferRequestMutationSchema)
.mutation(async ({ input, ctx }) => {
return await deleteTeamTransferRequest({
userId: ctx.user.id,
...input,
});
}),
// Internal endpoint for now.
findTeamInvoices: authenticatedProcedure
.input(ZFindTeamInvoicesQuerySchema)
.query(async ({ input, ctx }) => {
return await findTeamInvoices({
userId: ctx.user.id,
...input,
});
}),
findTeamMemberInvites: authenticatedProcedure
.meta({ openapi: { method: 'GET', path: '/team/{teamId}/member/invite' } })
.input(ZFindTeamMemberInvitesQuerySchema)
.output(ZFindTeamMemberInvitesResponseSchema)
.query(async ({ input, ctx }) => {
return await findTeamMemberInvites({
userId: ctx.user.id,
...input,
});
}),
findTeamMembers: authenticatedProcedure
.meta({ openapi: { method: 'GET', path: '/team/{teamId}/member' } })
.input(ZFindTeamMembersQuerySchema)
.output(ZFindTeamMembersResponseSchema)
.query(async ({ input, ctx }) => {
return await findTeamMembers({
userId: ctx.user.id,
...input,
});
}),
// Todo: Refactor, seems to be a redundant endpoint.
findTeams: authenticatedProcedure.input(ZFindTeamsQuerySchema).query(async ({ input, ctx }) => {
return await findTeams({
userId: ctx.user.id,
...input,
});
}),
findTeamsPending: authenticatedProcedure
.meta({ openapi: { method: 'GET', path: '/team-pending' } })
// .meta({
// openapi: {
// method: 'GET',
// path: '/team/pending',
// summary: 'Find pending teams',
// description: 'Find teams that are pending payment',
// tags: ['Teams'],
// },
// })
.input(ZFindTeamsPendingQuerySchema)
.output(ZFindTeamsPendingResponseSchema)
.query(async ({ input, ctx }) => {
return await findTeamsPending({
userId: ctx.user.id,
@ -295,187 +633,22 @@ export const teamRouter = router({
});
}),
getTeam: authenticatedProcedure
.meta({ openapi: { method: 'GET', path: '/team/{teamId}' } })
.input(ZGetTeamQuerySchema)
.output(ZGetTeamByIdResponseSchema)
.query(async ({ input, ctx }) => {
return await getTeamById({ teamId: input.teamId, userId: ctx.user.id });
}),
// Todo
getTeamEmailByEmail: authenticatedProcedure.query(async ({ ctx }) => {
return await getTeamEmailByEmail({ email: ctx.user.email });
}),
getTeamInvitations: authenticatedProcedure
.meta({ openapi: { method: 'GET', path: '/team/invite' } })
.input(z.void())
.output(ZGetTeamInvitationsResponseSchema)
.query(async ({ ctx }) => {
return await getTeamInvitations({ email: ctx.user.email });
}),
getTeamMembers: authenticatedProcedure
.meta({ openapi: { method: 'GET', path: '/team/member' } })
.input(ZGetTeamMembersQuerySchema)
.output(ZGetTeamMembersResponseSchema)
.query(async ({ input, ctx }) => {
return await getTeamMembers({ teamId: input.teamId, userId: ctx.user.id });
}),
// Internal endpoint for now.
getTeamPrices: authenticatedProcedure.query(async () => {
return await getTeamPrices();
}),
getTeams: authenticatedProcedure
.meta({ openapi: { method: 'GET', path: '/team' } })
.input(z.void())
.output(ZGetTeamsResponseSchema)
.query(async ({ ctx }) => {
return await getTeams({ userId: ctx.user.id });
}),
leaveTeam: authenticatedProcedure
.meta({ openapi: { method: 'POST', path: '/team/{teamId}/leave' } })
.input(ZLeaveTeamMutationSchema)
.output(z.void())
deleteTeamPending: authenticatedProcedure
// .meta({
// openapi: {
// method: 'POST',
// path: '/team/pending/{pendingTeamId}/delete',
// summary: 'Delete pending team',
// description: '',
// tags: ['Teams'],
// },
// })
.input(ZDeleteTeamPendingMutationSchema)
.mutation(async ({ input, ctx }) => {
return await leaveTeam({
return await deleteTeamPending({
userId: ctx.user.id,
...input,
});
}),
updateTeam: authenticatedProcedure
.meta({ openapi: { method: 'PATCH', path: '/team/{teamId}' } })
.input(ZUpdateTeamMutationSchema)
.output(z.void())
.mutation(async ({ input, ctx }) => {
return await updateTeam({
userId: ctx.user.id,
...input,
});
}),
updateTeamEmail: authenticatedProcedure
.meta({ openapi: { method: 'PATCH', path: '/team/{teamId}/email' } })
.input(ZUpdateTeamEmailMutationSchema)
.output(z.void())
.mutation(async ({ input, ctx }) => {
return await updateTeamEmail({
userId: ctx.user.id,
...input,
});
}),
updateTeamMember: authenticatedProcedure
.meta({ openapi: { method: 'PATCH', path: '/team/{teamId}/member' } })
.input(ZUpdateTeamMemberMutationSchema)
.output(z.void())
.mutation(async ({ input, ctx }) => {
return await updateTeamMember({
userId: ctx.user.id,
...input,
});
}),
updateTeamPublicProfile: authenticatedProcedure
.meta({ openapi: { method: 'PATCH', path: '/team/{teamId}/profile' } })
.input(ZUpdateTeamPublicProfileMutationSchema)
.output(z.void())
.mutation(async ({ input, ctx }) => {
try {
const { teamId, bio, enabled } = input;
await updateTeamPublicProfile({
userId: ctx.user.id,
teamId,
data: {
bio,
enabled,
},
});
} catch (err) {
console.error(err);
const error = AppError.parseError(err);
if (error.code !== AppErrorCode.UNKNOWN_ERROR) {
throw error;
}
throw new TRPCError({
code: 'BAD_REQUEST',
message:
'We were unable to update your public profile. Please review the information you provided and try again.',
});
}
}),
requestTeamOwnershipTransfer: authenticatedProcedure
.meta({ openapi: { method: 'POST', path: '/team/{teamId}/transfer' } })
.input(ZRequestTeamOwnerhsipTransferMutationSchema)
.output(z.void())
.mutation(async ({ input, ctx }) => {
return await requestTeamOwnershipTransfer({
userId: ctx.user.id,
userName: ctx.user.name ?? '',
...input,
});
}),
resendTeamEmailVerification: authenticatedProcedure
.meta({ openapi: { method: 'POST', path: '/team/{teamId}/email/resend' } })
.input(ZResendTeamEmailVerificationMutationSchema)
.output(z.void())
.mutation(async ({ input, ctx }) => {
await resendTeamEmailVerification({
userId: ctx.user.id,
...input,
});
}),
resendTeamMemberInvitation: authenticatedProcedure
.meta({
openapi: { method: 'POST', path: '/team/{teamId}/member/invite/{invitationId}/resend' },
})
.input(ZResendTeamMemberInvitationMutationSchema)
.output(z.void())
.mutation(async ({ input, ctx }) => {
await resendTeamMemberInvitation({
userId: ctx.user.id,
userName: ctx.user.name ?? '',
...input,
});
}),
updateTeamBrandingSettings: authenticatedProcedure
.meta({ openapi: { method: 'PATCH', path: '/team/{teamId}/branding' } })
.input(ZUpdateTeamBrandingSettingsMutationSchema)
.output(ZUpdateTeamBrandingSettingsResponseSchema)
.mutation(async ({ ctx, input }) => {
const { teamId, settings } = input;
return await updateTeamBrandingSettings({
userId: ctx.user.id,
teamId,
settings,
});
}),
updateTeamDocumentSettings: authenticatedProcedure
.meta({ openapi: { method: 'PATCH', path: '/team/{teamId}/settings' } })
.input(ZUpdateTeamDocumentSettingsMutationSchema)
.output(ZUpdateTeamDocumentSettingsResponseSchema)
.mutation(async ({ ctx, input }) => {
const { teamId, settings } = input;
return await updateTeamDocumentSettings({
userId: ctx.user.id,
teamId,
settings,
});
}),
});

View File

@ -1,4 +1,5 @@
import { TRPCError } from '@trpc/server';
import { z } from 'zod';
import { getServerLimits } from '@documenso/ee/server-only/limits/server';
import { isValidLanguageCode } from '@documenso/lib/constants/i18n';
@ -13,7 +14,6 @@ import { deleteTemplateDirectLink } from '@documenso/lib/server-only/template/de
import { duplicateTemplate } from '@documenso/lib/server-only/template/duplicate-template';
import { findTemplates } from '@documenso/lib/server-only/template/find-templates';
import { getTemplateById } from '@documenso/lib/server-only/template/get-template-by-id';
import { getTemplateWithDetailsById } from '@documenso/lib/server-only/template/get-template-with-details-by-id';
import { moveTemplateToTeam } from '@documenso/lib/server-only/template/move-template-to-team';
import { toggleTemplateDirectLink } from '@documenso/lib/server-only/template/toggle-template-direct-link';
import { updateTemplateSettings } from '@documenso/lib/server-only/template/update-template-settings';
@ -30,7 +30,7 @@ import {
ZDeleteTemplateMutationSchema,
ZDuplicateTemplateMutationSchema,
ZFindTemplatesQuerySchema,
ZGetTemplateWithDetailsByIdQuerySchema,
ZGetTemplateByIdQuerySchema,
ZMoveTemplatesToTeamSchema,
ZSetSigningOrderForTemplateMutationSchema,
ZToggleTemplateDirectLinkMutationSchema,
@ -39,8 +39,58 @@ import {
} from './schema';
export const templateRouter = router({
findTemplates: authenticatedProcedure
.meta({
openapi: {
method: 'GET',
path: '/template/find',
summary: 'Find templates',
description: 'Find templates based on a search criteria',
tags: ['Template'],
},
})
.input(ZFindTemplatesQuerySchema)
.output(z.unknown())
.query(async ({ input, ctx }) => {
return await findTemplates({
userId: ctx.user.id,
...input,
});
}),
getTemplateById: authenticatedProcedure
.meta({
openapi: {
method: 'GET',
path: '/template/{templateId}',
summary: 'Get template',
tags: ['Template'],
},
})
.input(ZGetTemplateByIdQuerySchema)
.output(z.unknown())
.query(async ({ input, ctx }) => {
const { templateId, teamId } = input;
return await getTemplateById({
id: templateId,
userId: ctx.user.id,
teamId,
});
}),
createTemplate: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/template/create',
summary: 'Create template',
description: 'Create a new template',
tags: ['Template'],
},
})
.input(ZCreateTemplateMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { teamId, title, templateDocumentDataId } = input;
@ -52,40 +102,89 @@ export const templateRouter = router({
});
}),
createDocumentFromDirectTemplate: maybeAuthenticatedProcedure
.input(ZCreateDocumentFromDirectTemplateMutationSchema)
updateTemplate: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/template/{templateId}',
summary: 'Update template',
tags: ['Template'],
},
})
.input(ZUpdateTemplateSettingsMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const {
directRecipientName,
directRecipientEmail,
directTemplateToken,
directTemplateExternalId,
signedFieldValues,
templateUpdatedAt,
} = input;
const { templateId, teamId, data, meta } = input;
const userId = ctx.user.id;
const requestMetadata = extractNextApiRequestMetadata(ctx.req);
return await createDocumentFromDirectTemplate({
directRecipientName,
directRecipientEmail,
directTemplateToken,
directTemplateExternalId,
signedFieldValues,
templateUpdatedAt,
user: ctx.user
? {
id: ctx.user.id,
name: ctx.user.name || undefined,
email: ctx.user.email,
}
: undefined,
return await updateTemplateSettings({
userId,
teamId,
templateId,
data,
meta: {
...meta,
language: isValidLanguageCode(meta?.language) ? meta?.language : undefined,
},
requestMetadata,
});
}),
duplicateTemplate: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/template/{templateId}/duplicate',
summary: 'Duplicate template',
tags: ['Template'],
},
})
.input(ZDuplicateTemplateMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { teamId, templateId } = input;
return await duplicateTemplate({
userId: ctx.user.id,
teamId,
templateId,
});
}),
deleteTemplate: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/template/{templateId}/delete',
summary: 'Delete template',
tags: ['Template'],
},
})
.input(ZDeleteTemplateMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { templateId, teamId } = input;
const userId = ctx.user.id;
await deleteTemplate({ userId, id: templateId, teamId });
}),
createDocumentFromTemplate: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/template/{templateId}/use',
summary: 'Use template',
description: 'Use the template to create a document',
tags: ['Template'],
},
})
.input(ZCreateDocumentFromTemplateMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { templateId, teamId, recipients } = input;
@ -121,60 +220,49 @@ export const templateRouter = router({
return document;
}),
duplicateTemplate: authenticatedProcedure
.input(ZDuplicateTemplateMutationSchema)
createDocumentFromDirectTemplate: maybeAuthenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/template/use',
summary: 'Use direct template',
description: 'Use a direct template to create a document',
tags: ['Template'],
},
})
.input(ZCreateDocumentFromDirectTemplateMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { teamId, templateId } = input;
return await duplicateTemplate({
userId: ctx.user.id,
teamId,
templateId,
});
}),
deleteTemplate: authenticatedProcedure
.input(ZDeleteTemplateMutationSchema)
.mutation(async ({ input, ctx }) => {
const { id, teamId } = input;
const userId = ctx.user.id;
return await deleteTemplate({ userId, id, teamId });
}),
getTemplateWithDetailsById: authenticatedProcedure
.input(ZGetTemplateWithDetailsByIdQuerySchema)
.query(async ({ input, ctx }) => {
return await getTemplateWithDetailsById({
id: input.id,
userId: ctx.user.id,
});
}),
// Todo: Add API
updateTemplateSettings: authenticatedProcedure
.input(ZUpdateTemplateSettingsMutationSchema)
.mutation(async ({ input, ctx }) => {
const { templateId, teamId, data, meta } = input;
const userId = ctx.user.id;
const {
directRecipientName,
directRecipientEmail,
directTemplateToken,
directTemplateExternalId,
signedFieldValues,
templateUpdatedAt,
} = input;
const requestMetadata = extractNextApiRequestMetadata(ctx.req);
return await updateTemplateSettings({
userId,
teamId,
templateId,
data,
meta: {
...meta,
language: isValidLanguageCode(meta?.language) ? meta?.language : undefined,
},
return await createDocumentFromDirectTemplate({
directRecipientName,
directRecipientEmail,
directTemplateToken,
directTemplateExternalId,
signedFieldValues,
templateUpdatedAt,
user: ctx.user
? {
id: ctx.user.id,
name: ctx.user.name || undefined,
email: ctx.user.email,
}
: undefined,
requestMetadata,
});
}),
// Internal endpoint for now.
setSigningOrderForTemplate: authenticatedProcedure
.input(ZSetSigningOrderForTemplateMutationSchema)
.mutation(async ({ input, ctx }) => {
@ -190,17 +278,18 @@ export const templateRouter = router({
});
}),
findTemplates: authenticatedProcedure
.input(ZFindTemplatesQuerySchema)
.query(async ({ input, ctx }) => {
return await findTemplates({
userId: ctx.user.id,
...input,
});
}),
createTemplateDirectLink: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/template/{templateId}/direct/create',
summary: 'Create direct link',
description: 'Create a direct link for a template',
tags: ['Template'],
},
})
.input(ZCreateTemplateDirectLinkMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { templateId, teamId, directRecipientId } = input;
@ -220,17 +309,37 @@ export const templateRouter = router({
}),
deleteTemplateDirectLink: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/template/{templateId}/direct/delete',
summary: 'Delete direct link',
description: 'Delete a direct link for a template',
tags: ['Template'],
},
})
.input(ZDeleteTemplateDirectLinkMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { templateId } = input;
const userId = ctx.user.id;
return await deleteTemplateDirectLink({ userId, templateId });
await deleteTemplateDirectLink({ userId, templateId });
}),
toggleTemplateDirectLink: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/template/{templateId}/direct/toggle',
summary: 'Toggle direct link',
description: 'Enable or disable a direct link for a template',
tags: ['Template'],
},
})
.input(ZToggleTemplateDirectLinkMutationSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { templateId, enabled } = input;
@ -240,7 +349,17 @@ export const templateRouter = router({
}),
moveTemplateToTeam: authenticatedProcedure
.meta({
openapi: {
method: 'POST',
path: '/template/{templateId}/move',
summary: 'Move template',
description: 'Move a template to a team',
tags: ['Template'],
},
})
.input(ZMoveTemplatesToTeamSchema)
.output(z.unknown())
.mutation(async ({ input, ctx }) => {
const { templateId, teamId } = input;
const userId = ctx.user.id;
@ -252,47 +371,34 @@ export const templateRouter = router({
});
}),
// Internal endpoint for now.
updateTemplateTypedSignatureSettings: authenticatedProcedure
.input(ZUpdateTemplateTypedSignatureSettingsMutationSchema)
.mutation(async ({ input, ctx }) => {
try {
const { templateId, teamId, typedSignatureEnabled } = input;
const { templateId, teamId, typedSignatureEnabled } = input;
const template = await getTemplateById({
id: templateId,
teamId,
userId: ctx.user.id,
}).catch(() => null);
if (!template) {
throw new TRPCError({
code: 'NOT_FOUND',
message: 'Template not found',
});
}
return await updateTemplateSettings({
templateId,
teamId,
userId: ctx.user.id,
data: {},
meta: {
typedSignatureEnabled,
},
requestMetadata: extractNextApiRequestMetadata(ctx.req),
});
} catch (err) {
console.error(err);
if (err instanceof TRPCError) {
throw err;
}
const template = await getTemplateById({
id: templateId,
userId: ctx.user.id,
teamId,
}).catch(() => null);
if (!template) {
throw new TRPCError({
code: 'BAD_REQUEST',
message:
'We were unable to update the settings for this template. Please try again later.',
code: 'NOT_FOUND',
message: 'Template not found',
});
}
return await updateTemplateSettings({
templateId,
teamId,
userId: ctx.user.id,
data: {},
meta: {
typedSignatureEnabled,
},
requestMetadata: extractNextApiRequestMetadata(ctx.req),
});
}),
});

View File

@ -70,7 +70,7 @@ export const ZToggleTemplateDirectLinkMutationSchema = z.object({
});
export const ZDeleteTemplateMutationSchema = z.object({
id: z.number().min(1),
templateId: z.number().min(1),
teamId: z.number().optional(),
});
@ -130,8 +130,9 @@ export const ZFindTemplatesQuerySchema = ZBaseTableSearchParamsSchema.extend({
type: z.nativeEnum(TemplateType).optional(),
});
export const ZGetTemplateWithDetailsByIdQuerySchema = z.object({
id: z.number().min(1),
export const ZGetTemplateByIdQuerySchema = z.object({
templateId: z.number().min(1),
teamId: z.number().optional(),
});
export const ZMoveTemplatesToTeamSchema = z.object({
@ -151,7 +152,5 @@ export type TCreateDocumentFromTemplateMutationSchema = z.infer<
>;
export type TDuplicateTemplateMutationSchema = z.infer<typeof ZDuplicateTemplateMutationSchema>;
export type TDeleteTemplateMutationSchema = z.infer<typeof ZDeleteTemplateMutationSchema>;
export type TGetTemplateWithDetailsByIdQuerySchema = z.infer<
typeof ZGetTemplateWithDetailsByIdQuerySchema
>;
export type TGetTemplateByIdQuerySchema = z.infer<typeof ZGetTemplateByIdQuerySchema>;
export type TMoveTemplatesToSchema = z.infer<typeof ZMoveTemplatesToTeamSchema>;