fix: refactor search routes (#1529)

Refactor find endpoints to be consistent in terms of input and output.
This commit is contained in:
David Nguyen
2024-12-11 19:39:50 +09:00
committed by GitHub
parent 3d7b28a92b
commit 5df1a6602e
35 changed files with 171 additions and 184 deletions

View File

@@ -40,7 +40,7 @@ export const AdminDocumentResults = () => {
const { data: findDocumentsData, isLoading: isFindDocumentsLoading } = const { data: findDocumentsData, isLoading: isFindDocumentsLoading } =
trpc.admin.findDocuments.useQuery( trpc.admin.findDocuments.useQuery(
{ {
term: debouncedTerm, query: debouncedTerm,
page: page || 1, page: page || 1,
perPage: perPage || 20, perPage: perPage || 20,
}, },

View File

@@ -11,7 +11,7 @@ import type { DateTimeFormatOptions } from 'luxon';
import { UAParser } from 'ua-parser-js'; import { UAParser } from 'ua-parser-js';
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import { ZBaseTableSearchParamsSchema } from '@documenso/lib/types/search-params'; import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params';
import { formatDocumentAuditLogAction } from '@documenso/lib/utils/document-audit-logs'; import { formatDocumentAuditLogAction } from '@documenso/lib/utils/document-audit-logs';
import { trpc } from '@documenso/trpc/react'; import { trpc } from '@documenso/trpc/react';
import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table'; import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table';
@@ -35,9 +35,7 @@ export const DocumentLogsDataTable = ({ documentId }: DocumentLogsDataTableProps
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const updateSearchParams = useUpdateSearchParams(); const updateSearchParams = useUpdateSearchParams();
const parsedSearchParams = ZBaseTableSearchParamsSchema.parse( const parsedSearchParams = ZUrlSearchParamsSchema.parse(Object.fromEntries(searchParams ?? []));
Object.fromEntries(searchParams ?? []),
);
const { data, isLoading, isInitialLoading, isLoadingError } = const { data, isLoading, isInitialLoading, isLoadingError } =
trpc.document.findDocumentAuditLogs.useQuery( trpc.document.findDocumentAuditLogs.useQuery(

View File

@@ -9,7 +9,7 @@ import { DateTime } from 'luxon';
import { useSession } from 'next-auth/react'; import { useSession } from 'next-auth/react';
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import type { FindResultSet } from '@documenso/lib/types/find-result-set'; import type { FindResultResponse } from '@documenso/lib/types/search-params';
import type { Document, Recipient, Team, User } from '@documenso/prisma/client'; import type { Document, Recipient, Team, User } from '@documenso/prisma/client';
import { ExtendedDocumentStatus } from '@documenso/prisma/types/extended-document-status'; import { ExtendedDocumentStatus } from '@documenso/prisma/types/extended-document-status';
import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table'; import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table';
@@ -24,7 +24,7 @@ import { DataTableActionDropdown } from './data-table-action-dropdown';
import { DataTableTitle } from './data-table-title'; import { DataTableTitle } from './data-table-title';
export type DocumentsDataTableProps = { export type DocumentsDataTableProps = {
results: FindResultSet< results: FindResultResponse<
Document & { Document & {
Recipient: Recipient[]; Recipient: Recipient[];
User: Pick<User, 'id' | 'name' | 'email'>; User: Pick<User, 'id' | 'name' | 'email'>;

View File

@@ -83,7 +83,7 @@ export const DocumentsPageView = async ({ searchParams = {}, team }: DocumentsPa
perPage, perPage,
period, period,
senderIds, senderIds,
search, query: search,
}); });
const getTabHref = (value: typeof status) => { const getTabHref = (value: typeof status) => {

View File

@@ -75,7 +75,7 @@ export const PublicProfilePageView = ({ user, team, profile }: PublicProfilePage
const enabledPrivateDirectTemplates = useMemo( const enabledPrivateDirectTemplates = useMemo(
() => () =>
(data?.templates ?? []).filter( (data?.data ?? []).filter(
(template): template is DirectTemplate => (template): template is DirectTemplate =>
template.directLink?.enabled === true && template.type !== TemplateType.PUBLIC, template.directLink?.enabled === true && template.type !== TemplateType.PUBLIC,
), ),

View File

@@ -52,7 +52,7 @@ export const PublicTemplatesDataTable = () => {
); );
const { directTemplates, publicDirectTemplates, privateDirectTemplates } = useMemo(() => { const { directTemplates, publicDirectTemplates, privateDirectTemplates } = useMemo(() => {
const directTemplates = (data?.templates ?? []).filter( const directTemplates = (data?.data ?? []).filter(
(template): template is DirectTemplate => template.directLink?.enabled === true, (template): template is DirectTemplate => template.directLink?.enabled === true,
); );

View File

@@ -12,7 +12,7 @@ import { UAParser } from 'ua-parser-js';
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import { USER_SECURITY_AUDIT_LOG_MAP } from '@documenso/lib/constants/auth'; import { USER_SECURITY_AUDIT_LOG_MAP } from '@documenso/lib/constants/auth';
import { ZBaseTableSearchParamsSchema } from '@documenso/lib/types/search-params'; import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params';
import { trpc } from '@documenso/trpc/react'; import { trpc } from '@documenso/trpc/react';
import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table'; import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table';
import { DataTable } from '@documenso/ui/primitives/data-table'; import { DataTable } from '@documenso/ui/primitives/data-table';
@@ -33,9 +33,7 @@ export const UserSecurityActivityDataTable = () => {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const updateSearchParams = useUpdateSearchParams(); const updateSearchParams = useUpdateSearchParams();
const parsedSearchParams = ZBaseTableSearchParamsSchema.parse( const parsedSearchParams = ZUrlSearchParamsSchema.parse(Object.fromEntries(searchParams ?? []));
Object.fromEntries(searchParams ?? []),
);
const { data, isLoading, isInitialLoading, isLoadingError } = const { data, isLoading, isInitialLoading, isLoadingError } =
trpc.profile.findUserSecurityAuditLogs.useQuery( trpc.profile.findUserSecurityAuditLogs.useQuery(

View File

@@ -9,7 +9,7 @@ import { useLingui } from '@lingui/react';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import { ZBaseTableSearchParamsSchema } from '@documenso/lib/types/search-params'; import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params';
import { trpc } from '@documenso/trpc/react'; import { trpc } from '@documenso/trpc/react';
import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table'; import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table';
import { DataTable } from '@documenso/ui/primitives/data-table'; import { DataTable } from '@documenso/ui/primitives/data-table';
@@ -27,9 +27,7 @@ export const UserPasskeysDataTable = () => {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const updateSearchParams = useUpdateSearchParams(); const updateSearchParams = useUpdateSearchParams();
const parsedSearchParams = ZBaseTableSearchParamsSchema.parse( const parsedSearchParams = ZUrlSearchParamsSchema.parse(Object.fromEntries(searchParams ?? []));
Object.fromEntries(searchParams ?? []),
);
const { data, isLoading, isInitialLoading, isLoadingError } = trpc.auth.findPasskeys.useQuery( const { data, isLoading, isInitialLoading, isLoadingError } = trpc.auth.findPasskeys.useQuery(
{ {

View File

@@ -12,7 +12,7 @@ import { DateTime } from 'luxon';
import { z } from 'zod'; import { z } from 'zod';
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import { ZBaseTableSearchParamsSchema } from '@documenso/lib/types/search-params'; import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params';
import type { Team } from '@documenso/prisma/client'; import type { Team } from '@documenso/prisma/client';
import { DocumentSource, DocumentStatus as DocumentStatusEnum } from '@documenso/prisma/client'; import { DocumentSource, DocumentStatus as DocumentStatusEnum } from '@documenso/prisma/client';
import { trpc } from '@documenso/trpc/react'; import { trpc } from '@documenso/trpc/react';
@@ -40,7 +40,7 @@ const DOCUMENT_SOURCE_LABELS: { [key in DocumentSource]: MessageDescriptor } = {
TEMPLATE_DIRECT_LINK: msg`Direct link`, TEMPLATE_DIRECT_LINK: msg`Direct link`,
}; };
const ZTemplateSearchParamsSchema = ZBaseTableSearchParamsSchema.extend({ const ZDocumentSearchParamsSchema = ZUrlSearchParamsSchema.extend({
source: z source: z
.nativeEnum(DocumentSource) .nativeEnum(DocumentSource)
.optional() .optional()
@@ -49,10 +49,6 @@ const ZTemplateSearchParamsSchema = ZBaseTableSearchParamsSchema.extend({
.nativeEnum(DocumentStatusEnum) .nativeEnum(DocumentStatusEnum)
.optional() .optional()
.catch(() => undefined), .catch(() => undefined),
search: z.coerce
.string()
.optional()
.catch(() => undefined),
}); });
type TemplatePageViewDocumentsTableProps = { type TemplatePageViewDocumentsTableProps = {
@@ -69,7 +65,7 @@ export const TemplatePageViewDocumentsTable = ({
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const updateSearchParams = useUpdateSearchParams(); const updateSearchParams = useUpdateSearchParams();
const parsedSearchParams = ZTemplateSearchParamsSchema.parse( const parsedSearchParams = ZDocumentSearchParamsSchema.parse(
Object.fromEntries(searchParams ?? []), Object.fromEntries(searchParams ?? []),
); );
@@ -80,7 +76,7 @@ export const TemplatePageViewDocumentsTable = ({
teamId: team?.id, teamId: team?.id,
page: parsedSearchParams.page, page: parsedSearchParams.page,
perPage: parsedSearchParams.perPage, perPage: parsedSearchParams.perPage,
search: parsedSearchParams.search, query: parsedSearchParams.query,
source: parsedSearchParams.source, source: parsedSearchParams.source,
status: parsedSearchParams.status, status: parsedSearchParams.status,
}, },

View File

@@ -29,7 +29,7 @@ export const TemplatesPageView = async ({ searchParams = {}, team }: TemplatesPa
const documentRootPath = formatDocumentsPath(team?.url); const documentRootPath = formatDocumentsPath(team?.url);
const templateRootPath = formatTemplatesPath(team?.url); const templateRootPath = formatTemplatesPath(team?.url);
const { templates, totalPages } = await findTemplates({ const { data: templates, totalPages } = await findTemplates({
userId: user.id, userId: user.id,
teamId: team?.id, teamId: team?.id,
page: page, page: page,

View File

@@ -11,7 +11,7 @@ import { useLingui } from '@lingui/react';
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import { NEXT_PUBLIC_WEBAPP_URL, WEBAPP_BASE_URL } from '@documenso/lib/constants/app'; import { NEXT_PUBLIC_WEBAPP_URL, WEBAPP_BASE_URL } from '@documenso/lib/constants/app';
import { TEAM_MEMBER_ROLE_MAP } from '@documenso/lib/constants/teams'; import { TEAM_MEMBER_ROLE_MAP } from '@documenso/lib/constants/teams';
import { ZBaseTableSearchParamsSchema } from '@documenso/lib/types/search-params'; import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params';
import { canExecuteTeamAction } from '@documenso/lib/utils/teams'; import { canExecuteTeamAction } from '@documenso/lib/utils/teams';
import { trpc } from '@documenso/trpc/react'; import { trpc } from '@documenso/trpc/react';
import { AvatarWithText } from '@documenso/ui/primitives/avatar'; import { AvatarWithText } from '@documenso/ui/primitives/avatar';
@@ -30,13 +30,11 @@ export const CurrentUserTeamsDataTable = () => {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const updateSearchParams = useUpdateSearchParams(); const updateSearchParams = useUpdateSearchParams();
const parsedSearchParams = ZBaseTableSearchParamsSchema.parse( const parsedSearchParams = ZUrlSearchParamsSchema.parse(Object.fromEntries(searchParams ?? []));
Object.fromEntries(searchParams ?? []),
);
const { data, isLoading, isInitialLoading, isLoadingError } = trpc.team.findTeams.useQuery( const { data, isLoading, isInitialLoading, isLoadingError } = trpc.team.findTeams.useQuery(
{ {
term: parsedSearchParams.query, query: parsedSearchParams.query,
page: parsedSearchParams.page, page: parsedSearchParams.page,
perPage: parsedSearchParams.perPage, perPage: parsedSearchParams.perPage,
}, },

View File

@@ -9,7 +9,7 @@ import { useLingui } from '@lingui/react';
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app'; import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app';
import { ZBaseTableSearchParamsSchema } from '@documenso/lib/types/search-params'; import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params';
import { trpc } from '@documenso/trpc/react'; import { trpc } from '@documenso/trpc/react';
import { AvatarWithText } from '@documenso/ui/primitives/avatar'; import { AvatarWithText } from '@documenso/ui/primitives/avatar';
import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table'; import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table';
@@ -27,15 +27,13 @@ export const PendingUserTeamsDataTable = () => {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const updateSearchParams = useUpdateSearchParams(); const updateSearchParams = useUpdateSearchParams();
const parsedSearchParams = ZBaseTableSearchParamsSchema.parse( const parsedSearchParams = ZUrlSearchParamsSchema.parse(Object.fromEntries(searchParams ?? []));
Object.fromEntries(searchParams ?? []),
);
const [checkoutPendingTeamId, setCheckoutPendingTeamId] = useState<number | null>(null); const [checkoutPendingTeamId, setCheckoutPendingTeamId] = useState<number | null>(null);
const { data, isLoading, isInitialLoading, isLoadingError } = trpc.team.findTeamsPending.useQuery( const { data, isLoading, isInitialLoading, isLoadingError } = trpc.team.findTeamsPending.useQuery(
{ {
term: parsedSearchParams.query, query: parsedSearchParams.query,
page: parsedSearchParams.page, page: parsedSearchParams.page,
perPage: parsedSearchParams.perPage, perPage: parsedSearchParams.perPage,
}, },

View File

@@ -10,7 +10,7 @@ import { History, MoreHorizontal, Trash2 } from 'lucide-react';
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import { TEAM_MEMBER_ROLE_MAP } from '@documenso/lib/constants/teams'; import { TEAM_MEMBER_ROLE_MAP } from '@documenso/lib/constants/teams';
import { ZBaseTableSearchParamsSchema } from '@documenso/lib/types/search-params'; import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params';
import { trpc } from '@documenso/trpc/react'; import { trpc } from '@documenso/trpc/react';
import { AvatarWithText } from '@documenso/ui/primitives/avatar'; import { AvatarWithText } from '@documenso/ui/primitives/avatar';
import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table'; import type { DataTableColumnDef } from '@documenso/ui/primitives/data-table';
@@ -38,15 +38,13 @@ export const TeamMemberInvitesDataTable = ({ teamId }: TeamMemberInvitesDataTabl
const { _, i18n } = useLingui(); const { _, i18n } = useLingui();
const { toast } = useToast(); const { toast } = useToast();
const parsedSearchParams = ZBaseTableSearchParamsSchema.parse( const parsedSearchParams = ZUrlSearchParamsSchema.parse(Object.fromEntries(searchParams ?? []));
Object.fromEntries(searchParams ?? []),
);
const { data, isLoading, isInitialLoading, isLoadingError } = const { data, isLoading, isInitialLoading, isLoadingError } =
trpc.team.findTeamMemberInvites.useQuery( trpc.team.findTeamMemberInvites.useQuery(
{ {
teamId, teamId,
term: parsedSearchParams.query, query: parsedSearchParams.query,
page: parsedSearchParams.page, page: parsedSearchParams.page,
perPage: parsedSearchParams.perPage, perPage: parsedSearchParams.perPage,
}, },

View File

@@ -10,7 +10,7 @@ import { Edit, MoreHorizontal, Trash2 } from 'lucide-react';
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params'; import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import { TEAM_MEMBER_ROLE_MAP } from '@documenso/lib/constants/teams'; import { TEAM_MEMBER_ROLE_MAP } from '@documenso/lib/constants/teams';
import { ZBaseTableSearchParamsSchema } from '@documenso/lib/types/search-params'; import { ZUrlSearchParamsSchema } from '@documenso/lib/types/search-params';
import { extractInitials } from '@documenso/lib/utils/recipient-formatter'; import { extractInitials } from '@documenso/lib/utils/recipient-formatter';
import { isTeamRoleWithinUserHierarchy } from '@documenso/lib/utils/teams'; import { isTeamRoleWithinUserHierarchy } from '@documenso/lib/utils/teams';
import type { TeamMemberRole } from '@documenso/prisma/client'; import type { TeamMemberRole } from '@documenso/prisma/client';
@@ -50,14 +50,12 @@ export const TeamMembersDataTable = ({
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const updateSearchParams = useUpdateSearchParams(); const updateSearchParams = useUpdateSearchParams();
const parsedSearchParams = ZBaseTableSearchParamsSchema.parse( const parsedSearchParams = ZUrlSearchParamsSchema.parse(Object.fromEntries(searchParams ?? []));
Object.fromEntries(searchParams ?? []),
);
const { data, isLoading, isInitialLoading, isLoadingError } = trpc.team.findTeamMembers.useQuery( const { data, isLoading, isInitialLoading, isLoadingError } = trpc.team.findTeamMembers.useQuery(
{ {
teamId, teamId,
term: parsedSearchParams.query, query: parsedSearchParams.query,
page: parsedSearchParams.page, page: parsedSearchParams.page,
perPage: parsedSearchParams.perPage, perPage: parsedSearchParams.perPage,
}, },

View File

@@ -427,7 +427,7 @@ export const ApiContractV1Implementation = createNextRoute(ApiContractV1, {
const perPage = Number(args.query.perPage) || 10; const perPage = Number(args.query.perPage) || 10;
try { try {
const { templates, totalPages } = await findTemplates({ const { data: templates, totalPages } = await findTemplates({
page, page,
perPage, perPage,
userId: user.id, userId: user.id,

View File

@@ -1,18 +1,20 @@
import { prisma } from '@documenso/prisma'; import { prisma } from '@documenso/prisma';
import type { Prisma } from '@documenso/prisma/client'; import type { Prisma } from '@documenso/prisma/client';
import type { FindResultResponse } from '../../types/search-params';
export interface FindDocumentsOptions { export interface FindDocumentsOptions {
term?: string; query?: string;
page?: number; page?: number;
perPage?: number; perPage?: number;
} }
export const findDocuments = async ({ term, page = 1, perPage = 10 }: FindDocumentsOptions) => { export const findDocuments = async ({ query, page = 1, perPage = 10 }: FindDocumentsOptions) => {
const termFilters: Prisma.DocumentWhereInput | undefined = !term const termFilters: Prisma.DocumentWhereInput | undefined = !query
? undefined ? undefined
: { : {
title: { title: {
contains: term, contains: query,
mode: 'insensitive', mode: 'insensitive',
}, },
}; };
@@ -51,5 +53,5 @@ export const findDocuments = async ({ term, page = 1, perPage = 10 }: FindDocume
currentPage: Math.max(page, 1), currentPage: Math.max(page, 1),
perPage, perPage,
totalPages: Math.ceil(count / perPage), totalPages: Math.ceil(count / perPage),
}; } satisfies FindResultResponse<typeof data>;
}; };

View File

@@ -1,11 +1,12 @@
import type { FindResultSet } from '@documenso/lib/types/find-result-set';
import { prisma } from '@documenso/prisma'; import { prisma } from '@documenso/prisma';
import type { Passkey } from '@documenso/prisma/client'; import type { Passkey } from '@documenso/prisma/client';
import { Prisma } from '@documenso/prisma/client'; import { Prisma } from '@documenso/prisma/client';
import type { FindResultResponse } from '../../types/search-params';
export interface FindPasskeysOptions { export interface FindPasskeysOptions {
userId: number; userId: number;
term?: string; query?: string;
page?: number; page?: number;
perPage?: number; perPage?: number;
orderBy?: { orderBy?: {
@@ -17,7 +18,7 @@ export interface FindPasskeysOptions {
export const findPasskeys = async ({ export const findPasskeys = async ({
userId, userId,
term = '', query = '',
page = 1, page = 1,
perPage = 10, perPage = 10,
orderBy, orderBy,
@@ -30,9 +31,9 @@ export const findPasskeys = async ({
userId, userId,
}; };
if (term.length > 0) { if (query.length > 0) {
whereClause.name = { whereClause.name = {
contains: term, contains: query,
mode: Prisma.QueryMode.insensitive, mode: Prisma.QueryMode.insensitive,
}; };
} }
@@ -72,5 +73,5 @@ export const findPasskeys = async ({
currentPage: Math.max(page, 1), currentPage: Math.max(page, 1),
perPage, perPage,
totalPages: Math.ceil(count / perPage), totalPages: Math.ceil(count / perPage),
} satisfies FindResultSet<typeof data>; } satisfies FindResultResponse<typeof data>;
}; };

View File

@@ -1,9 +1,9 @@
import type { FindResultSet } from '@documenso/lib/types/find-result-set';
import { prisma } from '@documenso/prisma'; import { prisma } from '@documenso/prisma';
import type { DocumentAuditLog } from '@documenso/prisma/client'; import type { DocumentAuditLog, Prisma } from '@documenso/prisma/client';
import type { Prisma } from '@documenso/prisma/client';
import { AppError, AppErrorCode } from '../../errors/app-error';
import { DOCUMENT_AUDIT_LOG_TYPE } from '../../types/document-audit-logs'; import { DOCUMENT_AUDIT_LOG_TYPE } from '../../types/document-audit-logs';
import type { FindResultResponse } from '../../types/search-params';
import { parseDocumentAuditLogData } from '../../utils/document-audit-logs'; import { parseDocumentAuditLogData } from '../../utils/document-audit-logs';
export interface FindDocumentAuditLogsOptions { export interface FindDocumentAuditLogsOptions {
@@ -31,7 +31,7 @@ export const findDocumentAuditLogs = async ({
const orderByColumn = orderBy?.column ?? 'createdAt'; const orderByColumn = orderBy?.column ?? 'createdAt';
const orderByDirection = orderBy?.direction ?? 'desc'; const orderByDirection = orderBy?.direction ?? 'desc';
const documentFilter = await prisma.document.findFirstOrThrow({ const document = await prisma.document.findFirst({
where: { where: {
id: documentId, id: documentId,
OR: [ OR: [
@@ -51,6 +51,10 @@ export const findDocumentAuditLogs = async ({
}, },
}); });
if (!document) {
throw new AppError(AppErrorCode.NOT_FOUND);
}
const whereClause: Prisma.DocumentAuditLogWhereInput = { const whereClause: Prisma.DocumentAuditLogWhereInput = {
documentId, documentId,
}; };
@@ -113,5 +117,5 @@ export const findDocumentAuditLogs = async ({
perPage, perPage,
totalPages: Math.ceil(count / perPage), totalPages: Math.ceil(count / perPage),
nextCursor, nextCursor,
} satisfies FindResultSet<typeof parsedData> & { nextCursor?: string }; } satisfies FindResultResponse<typeof parsedData> & { nextCursor?: string };
}; };

View File

@@ -1,8 +1,7 @@
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { P, match } from 'ts-pattern'; import { match } from 'ts-pattern';
import { prisma } from '@documenso/prisma'; import { prisma } from '@documenso/prisma';
import { RecipientRole, SigningStatus, TeamMemberRole } from '@documenso/prisma/client';
import type { import type {
Document, Document,
DocumentSource, DocumentSource,
@@ -11,10 +10,11 @@ import type {
TeamEmail, TeamEmail,
User, User,
} from '@documenso/prisma/client'; } from '@documenso/prisma/client';
import { RecipientRole, SigningStatus, TeamMemberRole } from '@documenso/prisma/client';
import { ExtendedDocumentStatus } from '@documenso/prisma/types/extended-document-status'; import { ExtendedDocumentStatus } from '@documenso/prisma/types/extended-document-status';
import { DocumentVisibility } from '../../types/document-visibility'; import { DocumentVisibility } from '../../types/document-visibility';
import type { FindResultSet } from '../../types/find-result-set'; import type { FindResultResponse } from '../../types/search-params';
import { maskRecipientTokensForDocument } from '../../utils/mask-recipient-tokens-for-document'; import { maskRecipientTokensForDocument } from '../../utils/mask-recipient-tokens-for-document';
export type PeriodSelectorValue = '' | '7d' | '14d' | '30d'; export type PeriodSelectorValue = '' | '7d' | '14d' | '30d';
@@ -22,7 +22,6 @@ export type PeriodSelectorValue = '' | '7d' | '14d' | '30d';
export type FindDocumentsOptions = { export type FindDocumentsOptions = {
userId: number; userId: number;
teamId?: number; teamId?: number;
term?: string;
templateId?: number; templateId?: number;
source?: DocumentSource; source?: DocumentSource;
status?: ExtendedDocumentStatus; status?: ExtendedDocumentStatus;
@@ -34,13 +33,12 @@ export type FindDocumentsOptions = {
}; };
period?: PeriodSelectorValue; period?: PeriodSelectorValue;
senderIds?: number[]; senderIds?: number[];
search?: string; query?: string;
}; };
export const findDocuments = async ({ export const findDocuments = async ({
userId, userId,
teamId, teamId,
term,
templateId, templateId,
source, source,
status = ExtendedDocumentStatus.ALL, status = ExtendedDocumentStatus.ALL,
@@ -49,7 +47,7 @@ export const findDocuments = async ({
orderBy, orderBy,
period, period,
senderIds, senderIds,
search, query,
}: FindDocumentsOptions) => { }: FindDocumentsOptions) => {
const user = await prisma.user.findFirstOrThrow({ const user = await prisma.user.findFirstOrThrow({
where: { where: {
@@ -87,22 +85,11 @@ export const findDocuments = async ({
const orderByDirection = orderBy?.direction ?? 'desc'; const orderByDirection = orderBy?.direction ?? 'desc';
const teamMemberRole = team?.members[0].role ?? null; const teamMemberRole = team?.members[0].role ?? null;
const termFilters = match(term)
.with(P.string.minLength(1), () => {
return {
title: {
contains: term,
mode: 'insensitive',
},
} as const;
})
.otherwise(() => undefined);
const searchFilter: Prisma.DocumentWhereInput = { const searchFilter: Prisma.DocumentWhereInput = {
OR: [ OR: [
{ title: { contains: search, mode: 'insensitive' } }, { title: { contains: query, mode: 'insensitive' } },
{ Recipient: { some: { name: { contains: search, mode: 'insensitive' } } } }, { Recipient: { some: { name: { contains: query, mode: 'insensitive' } } } },
{ Recipient: { some: { email: { contains: search, mode: 'insensitive' } } } }, { Recipient: { some: { email: { contains: query, mode: 'insensitive' } } } },
], ],
}; };
@@ -209,7 +196,6 @@ export const findDocuments = async ({
} }
const whereAndClause: Prisma.DocumentWhereInput['AND'] = [ const whereAndClause: Prisma.DocumentWhereInput['AND'] = [
{ ...termFilters },
{ ...filters }, { ...filters },
{ ...deletedFilter }, { ...deletedFilter },
{ ...searchFilter }, { ...searchFilter },
@@ -290,7 +276,7 @@ export const findDocuments = async ({
currentPage: Math.max(page, 1), currentPage: Math.max(page, 1),
perPage, perPage,
totalPages: Math.ceil(count / perPage), totalPages: Math.ceil(count / perPage),
} satisfies FindResultSet<typeof data>; } satisfies FindResultResponse<typeof data>;
}; };
const findDocumentsFilter = (status: ExtendedDocumentStatus, user: User) => { const findDocumentsFilter = (status: ExtendedDocumentStatus, user: User) => {

View File

@@ -7,12 +7,12 @@ import { Prisma } from '@documenso/prisma/client';
import { TeamMemberInviteSchema } from '@documenso/prisma/generated/zod'; import { TeamMemberInviteSchema } from '@documenso/prisma/generated/zod';
import { TEAM_MEMBER_ROLE_PERMISSIONS_MAP } from '../../constants/teams'; import { TEAM_MEMBER_ROLE_PERMISSIONS_MAP } from '../../constants/teams';
import { type FindResultSet, ZFindResultSet } from '../../types/find-result-set'; import { type FindResultResponse, ZFindResultResponse } from '../../types/search-params';
export interface FindTeamMemberInvitesOptions { export interface FindTeamMemberInvitesOptions {
userId: number; userId: number;
teamId: number; teamId: number;
term?: string; query?: string;
page?: number; page?: number;
perPage?: number; perPage?: number;
orderBy?: { orderBy?: {
@@ -21,7 +21,7 @@ export interface FindTeamMemberInvitesOptions {
}; };
} }
export const ZFindTeamMemberInvitesResponseSchema = ZFindResultSet.extend({ export const ZFindTeamMemberInvitesResponseSchema = ZFindResultResponse.extend({
data: TeamMemberInviteSchema.pick({ data: TeamMemberInviteSchema.pick({
id: true, id: true,
teamId: true, teamId: true,
@@ -36,7 +36,7 @@ export type TFindTeamMemberInvitesResponse = z.infer<typeof ZFindTeamMemberInvit
export const findTeamMemberInvites = async ({ export const findTeamMemberInvites = async ({
userId, userId,
teamId, teamId,
term, query,
page = 1, page = 1,
perPage = 10, perPage = 10,
orderBy, orderBy,
@@ -59,10 +59,10 @@ export const findTeamMemberInvites = async ({
}, },
}); });
const termFilters: Prisma.TeamMemberInviteWhereInput | undefined = match(term) const termFilters: Prisma.TeamMemberInviteWhereInput | undefined = match(query)
.with(P.string.minLength(1), () => ({ .with(P.string.minLength(1), () => ({
email: { email: {
contains: term, contains: query,
mode: Prisma.QueryMode.insensitive, mode: Prisma.QueryMode.insensitive,
}, },
})) }))
@@ -101,5 +101,5 @@ export const findTeamMemberInvites = async ({
currentPage: Math.max(page, 1), currentPage: Math.max(page, 1),
perPage, perPage,
totalPages: Math.ceil(count / perPage), totalPages: Math.ceil(count / perPage),
} satisfies FindResultSet<typeof data>; } satisfies FindResultResponse<typeof data>;
}; };

View File

@@ -6,12 +6,13 @@ import type { TeamMember } from '@documenso/prisma/client';
import { Prisma } from '@documenso/prisma/client'; import { Prisma } from '@documenso/prisma/client';
import { TeamMemberSchema, UserSchema } from '@documenso/prisma/generated/zod'; import { TeamMemberSchema, UserSchema } from '@documenso/prisma/generated/zod';
import { type FindResultSet, ZFindResultSet } from '../../types/find-result-set'; import type { FindResultResponse } from '../../types/search-params';
import { ZFindResultResponse } from '../../types/search-params';
export interface FindTeamMembersOptions { export interface FindTeamMembersOptions {
userId: number; userId: number;
teamId: number; teamId: number;
term?: string; query?: string;
page?: number; page?: number;
perPage?: number; perPage?: number;
orderBy?: { orderBy?: {
@@ -20,7 +21,7 @@ export interface FindTeamMembersOptions {
}; };
} }
export const ZFindTeamMembersResponseSchema = ZFindResultSet.extend({ export const ZFindTeamMembersResponseSchema = ZFindResultResponse.extend({
data: TeamMemberSchema.extend({ data: TeamMemberSchema.extend({
user: UserSchema.pick({ user: UserSchema.pick({
name: true, name: true,
@@ -34,7 +35,7 @@ export type TFindTeamMembersResponse = z.infer<typeof ZFindTeamMembersResponseSc
export const findTeamMembers = async ({ export const findTeamMembers = async ({
userId, userId,
teamId, teamId,
term, query,
page = 1, page = 1,
perPage = 10, perPage = 10,
orderBy, orderBy,
@@ -54,11 +55,11 @@ export const findTeamMembers = async ({
}, },
}); });
const termFilters: Prisma.TeamMemberWhereInput | undefined = match(term) const termFilters: Prisma.TeamMemberWhereInput | undefined = match(query)
.with(P.string.minLength(1), () => ({ .with(P.string.minLength(1), () => ({
user: { user: {
name: { name: {
contains: term, contains: query,
mode: Prisma.QueryMode.insensitive, mode: Prisma.QueryMode.insensitive,
}, },
}, },
@@ -109,5 +110,5 @@ export const findTeamMembers = async ({
currentPage: Math.max(page, 1), currentPage: Math.max(page, 1),
perPage, perPage,
totalPages: Math.ceil(count / perPage), totalPages: Math.ceil(count / perPage),
} satisfies FindResultSet<typeof data>; } satisfies FindResultResponse<typeof data>;
}; };

View File

@@ -5,11 +5,11 @@ import type { Team } from '@documenso/prisma/client';
import { Prisma } from '@documenso/prisma/client'; import { Prisma } from '@documenso/prisma/client';
import { TeamPendingSchema } from '@documenso/prisma/generated/zod'; import { TeamPendingSchema } from '@documenso/prisma/generated/zod';
import { type FindResultSet, ZFindResultSet } from '../../types/find-result-set'; import { type FindResultResponse, ZFindResultResponse } from '../../types/search-params';
export interface FindTeamsPendingOptions { export interface FindTeamsPendingOptions {
userId: number; userId: number;
term?: string; query?: string;
page?: number; page?: number;
perPage?: number; perPage?: number;
orderBy?: { orderBy?: {
@@ -18,7 +18,7 @@ export interface FindTeamsPendingOptions {
}; };
} }
export const ZFindTeamsPendingResponseSchema = ZFindResultSet.extend({ export const ZFindTeamsPendingResponseSchema = ZFindResultResponse.extend({
data: TeamPendingSchema.array(), data: TeamPendingSchema.array(),
}); });
@@ -26,7 +26,7 @@ export type TFindTeamsPendingResponse = z.infer<typeof ZFindTeamsPendingResponse
export const findTeamsPending = async ({ export const findTeamsPending = async ({
userId, userId,
term, query,
page = 1, page = 1,
perPage = 10, perPage = 10,
orderBy, orderBy,
@@ -38,9 +38,9 @@ export const findTeamsPending = async ({
ownerUserId: userId, ownerUserId: userId,
}; };
if (term && term.length > 0) { if (query && query.length > 0) {
whereClause.name = { whereClause.name = {
contains: term, contains: query,
mode: Prisma.QueryMode.insensitive, mode: Prisma.QueryMode.insensitive,
}; };
} }
@@ -65,5 +65,5 @@ export const findTeamsPending = async ({
currentPage: Math.max(page, 1), currentPage: Math.max(page, 1),
perPage, perPage,
totalPages: Math.ceil(count / perPage), totalPages: Math.ceil(count / perPage),
} satisfies FindResultSet<typeof data>; } satisfies FindResultResponse<typeof data>;
}; };

View File

@@ -1,11 +1,12 @@
import type { FindResultSet } from '@documenso/lib/types/find-result-set';
import { prisma } from '@documenso/prisma'; import { prisma } from '@documenso/prisma';
import type { Team } from '@documenso/prisma/client'; import type { Team } from '@documenso/prisma/client';
import { Prisma } from '@documenso/prisma/client'; import { Prisma } from '@documenso/prisma/client';
import type { FindResultResponse } from '../../types/search-params';
export interface FindTeamsOptions { export interface FindTeamsOptions {
userId: number; userId: number;
term?: string; query?: string;
page?: number; page?: number;
perPage?: number; perPage?: number;
orderBy?: { orderBy?: {
@@ -16,7 +17,7 @@ export interface FindTeamsOptions {
export const findTeams = async ({ export const findTeams = async ({
userId, userId,
term, query,
page = 1, page = 1,
perPage = 10, perPage = 10,
orderBy, orderBy,
@@ -32,9 +33,9 @@ export const findTeams = async ({
}, },
}; };
if (term && term.length > 0) { if (query && query.length > 0) {
whereClause.name = { whereClause.name = {
contains: term, contains: query,
mode: Prisma.QueryMode.insensitive, mode: Prisma.QueryMode.insensitive,
}; };
} }
@@ -72,5 +73,5 @@ export const findTeams = async ({
currentPage: Math.max(page, 1), currentPage: Math.max(page, 1),
perPage, perPage,
totalPages: Math.ceil(count / perPage), totalPages: Math.ceil(count / perPage),
} satisfies FindResultSet<typeof maskedData>; } satisfies FindResultResponse<typeof maskedData>;
}; };

View File

@@ -1,6 +1,8 @@
import { prisma } from '@documenso/prisma'; import { prisma } from '@documenso/prisma';
import type { Prisma, Template } from '@documenso/prisma/client'; import type { Prisma, Template } from '@documenso/prisma/client';
import type { FindResultResponse } from '../../types/search-params';
export type FindTemplatesOptions = { export type FindTemplatesOptions = {
userId: number; userId: number;
teamId?: number; teamId?: number;
@@ -10,7 +12,7 @@ export type FindTemplatesOptions = {
}; };
export type FindTemplatesResponse = Awaited<ReturnType<typeof findTemplates>>; export type FindTemplatesResponse = Awaited<ReturnType<typeof findTemplates>>;
export type FindTemplateRow = FindTemplatesResponse['templates'][number]; export type FindTemplateRow = FindTemplatesResponse['data'][number];
export const findTemplates = async ({ export const findTemplates = async ({
userId, userId,
@@ -38,7 +40,7 @@ export const findTemplates = async ({
}; };
} }
const [templates, count] = await Promise.all([ const [data, count] = await Promise.all([
prisma.template.findMany({ prisma.template.findMany({
where: whereFilter, where: whereFilter,
include: { include: {
@@ -75,7 +77,10 @@ export const findTemplates = async ({
]); ]);
return { return {
templates, data,
count,
currentPage: Math.max(page, 1),
perPage,
totalPages: Math.ceil(count / perPage), totalPages: Math.ceil(count / perPage),
}; } satisfies FindResultResponse<typeof data>;
}; };

View File

@@ -1,7 +1,8 @@
import type { FindResultSet } from '@documenso/lib/types/find-result-set';
import { prisma } from '@documenso/prisma'; import { prisma } from '@documenso/prisma';
import type { UserSecurityAuditLog, UserSecurityAuditLogType } from '@documenso/prisma/client'; import type { UserSecurityAuditLog, UserSecurityAuditLogType } from '@documenso/prisma/client';
import type { FindResultResponse } from '../../types/search-params';
export type FindUserSecurityAuditLogsOptions = { export type FindUserSecurityAuditLogsOptions = {
userId: number; userId: number;
type?: UserSecurityAuditLogType; type?: UserSecurityAuditLogType;
@@ -48,5 +49,5 @@ export const findUserSecurityAuditLogs = async ({
currentPage: Math.max(page, 1), currentPage: Math.max(page, 1),
perPage, perPage,
totalPages: Math.ceil(count / perPage), totalPages: Math.ceil(count / perPage),
} satisfies FindResultSet<typeof data>; } satisfies FindResultResponse<typeof data>;
}; };

View File

@@ -1,18 +0,0 @@
import { z } from 'zod';
export const ZFindResultSet = z.object({
data: z.union([z.array(z.unknown()), z.unknown()]),
count: z.number(),
currentPage: z.number(),
perPage: z.number(),
totalPages: z.number(),
});
// Can't infer generics from Zod.
export type FindResultSet<T> = {
data: T extends Array<unknown> ? T : T[];
count: number;
currentPage: number;
perPage: number;
totalPages: number;
};

View File

@@ -1,6 +1,24 @@
import { z } from 'zod'; import { z } from 'zod';
export const ZBaseTableSearchParamsSchema = z.object({ /**
* Backend only schema is used for find search params.
*
* Does not catch, because TRPC Open API won't allow catches as a type.
*
* Keep this and `ZUrlSearchParamsSchema` in sync.
*/
export const ZFindSearchParamsSchema = z.object({
query: z.string().optional(),
page: z.coerce.number().min(1).optional(),
perPage: z.coerce.number().min(1).optional(),
});
/**
* Frontend schema used to parse search params from URL.
*
* Keep this and `ZFindSearchParamsSchema` in sync.
*/
export const ZUrlSearchParamsSchema = z.object({
query: z query: z
.string() .string()
.optional() .optional()
@@ -17,4 +35,19 @@ export const ZBaseTableSearchParamsSchema = z.object({
.catch(() => undefined), .catch(() => undefined),
}); });
export type TBaseTableSearchParamsSchema = z.infer<typeof ZBaseTableSearchParamsSchema>; export const ZFindResultResponse = z.object({
data: z.union([z.array(z.unknown()), z.unknown()]),
count: z.number(),
currentPage: z.number(),
perPage: z.number(),
totalPages: z.number(),
});
// Can't infer generics from Zod.
export type FindResultResponse<T> = {
data: T extends Array<unknown> ? T : T[];
count: number;
currentPage: number;
perPage: number;
totalPages: number;
};

View File

@@ -24,9 +24,9 @@ import {
export const adminRouter = router({ export const adminRouter = router({
findDocuments: adminProcedure.input(ZAdminFindDocumentsQuerySchema).query(async ({ input }) => { findDocuments: adminProcedure.input(ZAdminFindDocumentsQuerySchema).query(async ({ input }) => {
const { term, page, perPage } = input; const { query, page, perPage } = input;
return await findDocuments({ term, page, perPage }); return await findDocuments({ query, page, perPage });
}), }),
updateUser: adminProcedure updateUser: adminProcedure

View File

@@ -2,10 +2,9 @@ import { Role } from '@prisma/client';
import z from 'zod'; import z from 'zod';
import { ZSiteSettingSchema } from '@documenso/lib/server-only/site-settings/schema'; import { ZSiteSettingSchema } from '@documenso/lib/server-only/site-settings/schema';
import { ZFindSearchParamsSchema } from '@documenso/lib/types/search-params';
export const ZAdminFindDocumentsQuerySchema = z.object({ export const ZAdminFindDocumentsQuerySchema = ZFindSearchParamsSchema.extend({
term: z.string().optional(),
page: z.number().optional().default(1),
perPage: z.number().optional().default(20), perPage: z.number().optional().default(20),
}); });

View File

@@ -1,6 +1,6 @@
import { z } from 'zod'; import { z } from 'zod';
import { ZBaseTableSearchParamsSchema } from '@documenso/lib/types/search-params'; import { ZFindSearchParamsSchema } from '@documenso/lib/types/search-params';
import { ZRegistrationResponseJSONSchema } from '@documenso/lib/types/webauthn'; import { ZRegistrationResponseJSONSchema } from '@documenso/lib/types/webauthn';
export const ZCurrentPasswordSchema = z export const ZCurrentPasswordSchema = z
@@ -55,7 +55,7 @@ export const ZUpdatePasskeyMutationSchema = z.object({
name: z.string().trim().min(1), name: z.string().trim().min(1),
}); });
export const ZFindPasskeysQuerySchema = ZBaseTableSearchParamsSchema.extend({ export const ZFindPasskeysQuerySchema = ZFindSearchParamsSchema.extend({
orderBy: z orderBy: z
.object({ .object({
column: z.enum(['createdAt', 'updatedAt', 'name']), column: z.enum(['createdAt', 'updatedAt', 'name']),

View File

@@ -86,13 +86,13 @@ export const documentRouter = router({
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
const { user } = ctx; const { user } = ctx;
const { search, teamId, templateId, page, perPage, orderBy, source, status } = input; const { query, teamId, templateId, page, perPage, orderBy, source, status } = input;
const documents = await findDocuments({ const documents = await findDocuments({
userId: user.id, userId: user.id,
teamId, teamId,
templateId, templateId,
search, query,
source, source,
status, status,
page, page,

View File

@@ -6,7 +6,7 @@ import {
ZDocumentActionAuthTypesSchema, ZDocumentActionAuthTypesSchema,
} from '@documenso/lib/types/document-auth'; } from '@documenso/lib/types/document-auth';
import { ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email'; import { ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email';
import { ZBaseTableSearchParamsSchema } from '@documenso/lib/types/search-params'; import { ZFindSearchParamsSchema } from '@documenso/lib/types/search-params';
import { isValidRedirectUrl } from '@documenso/lib/utils/is-valid-redirect-url'; import { isValidRedirectUrl } from '@documenso/lib/utils/is-valid-redirect-url';
import { import {
DocumentDistributionMethod, DocumentDistributionMethod,
@@ -18,13 +18,9 @@ import {
RecipientRole, RecipientRole,
} from '@documenso/prisma/client'; } from '@documenso/prisma/client';
export const ZFindDocumentsQuerySchema = ZBaseTableSearchParamsSchema.extend({ export const ZFindDocumentsQuerySchema = ZFindSearchParamsSchema.extend({
teamId: z.number().min(1).optional(), teamId: z.number().min(1).optional(),
templateId: z.number().min(1).optional(), templateId: z.number().min(1).optional(),
search: z
.string()
.optional()
.catch(() => undefined),
source: z.nativeEnum(DocumentSource).optional(), source: z.nativeEnum(DocumentSource).optional(),
status: z.nativeEnum(DocumentStatus).optional(), status: z.nativeEnum(DocumentStatus).optional(),
orderBy: z orderBy: z
@@ -33,9 +29,9 @@ export const ZFindDocumentsQuerySchema = ZBaseTableSearchParamsSchema.extend({
direction: z.enum(['asc', 'desc']), direction: z.enum(['asc', 'desc']),
}) })
.optional(), .optional(),
}).omit({ query: true }); });
export const ZFindDocumentAuditLogsQuerySchema = ZBaseTableSearchParamsSchema.extend({ export const ZFindDocumentAuditLogsQuerySchema = ZFindSearchParamsSchema.extend({
documentId: z.number().min(1), documentId: z.number().min(1),
cursor: z.string().optional(), cursor: z.string().optional(),
filterForRecentActivity: z.boolean().optional(), filterForRecentActivity: z.boolean().optional(),

View File

@@ -74,20 +74,28 @@ import {
} from './schema'; } from './schema';
export const teamRouter = router({ export const teamRouter = router({
getTeams: authenticatedProcedure // Internal endpoint for now.
getTeams: authenticatedProcedure.query(async ({ ctx }) => {
return await getTeams({ userId: ctx.user.id });
}),
findTeams: authenticatedProcedure
.meta({ .meta({
openapi: { openapi: {
method: 'GET', method: 'GET',
path: '/team', path: '/team',
summary: 'Get teams', summary: 'Find teams',
description: 'Returns all teams that you are a member of', description: 'Find your teams based on a search criteria',
tags: ['Teams'], tags: ['Teams'],
}, },
}) })
.input(z.void()) .input(ZFindTeamsQuerySchema)
.output(z.unknown()) .output(z.unknown())
.query(async ({ ctx }) => { .query(async ({ input, ctx }) => {
return await getTeams({ userId: ctx.user.id }); return await findTeams({
userId: ctx.user.id,
...input,
});
}), }),
getTeam: authenticatedProcedure getTeam: authenticatedProcedure
@@ -327,14 +335,6 @@ export const teamRouter = router({
}); });
}), }),
// 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. // Internal endpoint for now.
createTeamEmailVerification: authenticatedProcedure createTeamEmailVerification: authenticatedProcedure
// .meta({ // .meta({

View File

@@ -2,17 +2,11 @@ import { z } from 'zod';
import { SUPPORTED_LANGUAGE_CODES } from '@documenso/lib/constants/i18n'; import { SUPPORTED_LANGUAGE_CODES } from '@documenso/lib/constants/i18n';
import { PROTECTED_TEAM_URLS } from '@documenso/lib/constants/teams'; import { PROTECTED_TEAM_URLS } from '@documenso/lib/constants/teams';
import { ZFindSearchParamsSchema } from '@documenso/lib/types/search-params';
import { DocumentVisibility, TeamMemberRole } from '@documenso/prisma/client'; import { DocumentVisibility, TeamMemberRole } from '@documenso/prisma/client';
import { ZUpdatePublicProfileMutationSchema } from '../profile-router/schema'; import { ZUpdatePublicProfileMutationSchema } from '../profile-router/schema';
// Consider refactoring to use ZBaseTableSearchParamsSchema.
const GenericFindQuerySchema = z.object({
term: z.string().optional(),
page: z.number().min(1).optional(),
perPage: z.number().min(1).optional(),
});
/** /**
* Restrict team URLs schema. * Restrict team URLs schema.
* *
@@ -122,17 +116,17 @@ export const ZFindTeamInvoicesQuerySchema = z.object({
teamId: z.number(), teamId: z.number(),
}); });
export const ZFindTeamMemberInvitesQuerySchema = GenericFindQuerySchema.extend({ export const ZFindTeamMemberInvitesQuerySchema = ZFindSearchParamsSchema.extend({
teamId: z.number(), teamId: z.number(),
}); });
export const ZFindTeamMembersQuerySchema = GenericFindQuerySchema.extend({ export const ZFindTeamMembersQuerySchema = ZFindSearchParamsSchema.extend({
teamId: z.number(), teamId: z.number(),
}); });
export const ZFindTeamsQuerySchema = GenericFindQuerySchema; export const ZFindTeamsQuerySchema = ZFindSearchParamsSchema;
export const ZFindTeamsPendingQuerySchema = GenericFindQuerySchema; export const ZFindTeamsPendingQuerySchema = ZFindSearchParamsSchema;
export const ZGetTeamQuerySchema = z.object({ export const ZGetTeamQuerySchema = z.object({
teamId: z.number(), teamId: z.number(),

View File

@@ -6,7 +6,7 @@ import {
ZDocumentActionAuthTypesSchema, ZDocumentActionAuthTypesSchema,
} from '@documenso/lib/types/document-auth'; } from '@documenso/lib/types/document-auth';
import { ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email'; import { ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email';
import { ZBaseTableSearchParamsSchema } from '@documenso/lib/types/search-params'; import { ZFindSearchParamsSchema } from '@documenso/lib/types/search-params';
import { isValidRedirectUrl } from '@documenso/lib/utils/is-valid-redirect-url'; import { isValidRedirectUrl } from '@documenso/lib/utils/is-valid-redirect-url';
import { import {
DocumentDistributionMethod, DocumentDistributionMethod,
@@ -125,7 +125,7 @@ export const ZSetSigningOrderForTemplateMutationSchema = z.object({
signingOrder: z.nativeEnum(DocumentSigningOrder), signingOrder: z.nativeEnum(DocumentSigningOrder),
}); });
export const ZFindTemplatesQuerySchema = ZBaseTableSearchParamsSchema.extend({ export const ZFindTemplatesQuerySchema = ZFindSearchParamsSchema.extend({
teamId: z.number().optional(), teamId: z.number().optional(),
type: z.nativeEnum(TemplateType).optional(), type: z.nativeEnum(TemplateType).optional(),
}); });