mirror of
https://github.com/documenso/documenso.git
synced 2025-11-11 13:02:31 +10:00
## Description
**Fixes issues with mismatching state between document steps.**
For example, editing a recipient and proceeding to the next step may not
display the updated recipient. And going back will display the old
recipient instead of the updated values.
**This PR also improves mutation and query speeds by adding logic to
bypass query invalidation.**
```ts
export const trpc = createTRPCReact<AppRouter>({
unstable_overrides: {
useMutation: {
async onSuccess(opts) {
await opts.originalFn();
// This forces mutations to wait for all the queries on the page to reload, and in
// this case one of the queries is `searchDocument` for the command overlay, which
// on average takes ~500ms. This means that every single mutation must wait for this.
await opts.queryClient.invalidateQueries();
},
},
},
});
```
I've added workarounds to allow us to bypass things such as batching and
invalidating queries. But I think we should instead remove this and
update all the mutations where a query is required for a more optimised
system.
## Example benchmarks
Using stg-app vs this preview there's an average 50% speed increase
across mutations.
**Set signer step:**
Average old speed: ~1100ms
Average new speed: ~550ms
**Set recipient step:**
Average old speed: ~1200ms
Average new speed: ~600ms
**Set fields step:**
Average old speed: ~1200ms
Average new speed: ~600ms
## Related Issue
This will resolve #470
## Changes Made
- Added ability to skip batch queries
- Added a state to store the required document data.
- Refetch the data between steps if/when required
- Optimise mutations and queries
## Checklist
- [X] I have tested these changes locally and they work as expected.
- [X] I have followed the project's coding style guidelines.
---------
Co-authored-by: Lucas Smith <me@lucasjamessmith.me>
138 lines
3.9 KiB
TypeScript
138 lines
3.9 KiB
TypeScript
import { z } from 'zod';
|
|
|
|
import { URL_REGEX } from '@documenso/lib/constants/url-regex';
|
|
import { ZBaseTableSearchParamsSchema } from '@documenso/lib/types/search-params';
|
|
import { FieldType, RecipientRole } from '@documenso/prisma/client';
|
|
|
|
export const ZFindDocumentAuditLogsQuerySchema = ZBaseTableSearchParamsSchema.extend({
|
|
documentId: z.number().min(1),
|
|
cursor: z.string().optional(),
|
|
filterForRecentActivity: z.boolean().optional(),
|
|
orderBy: z
|
|
.object({
|
|
column: z.enum(['createdAt', 'type']),
|
|
direction: z.enum(['asc', 'desc']),
|
|
})
|
|
.optional(),
|
|
});
|
|
|
|
export const ZGetDocumentByIdQuerySchema = z.object({
|
|
id: z.number().min(1),
|
|
teamId: z.number().min(1).optional(),
|
|
});
|
|
|
|
export type TGetDocumentByIdQuerySchema = z.infer<typeof ZGetDocumentByIdQuerySchema>;
|
|
|
|
export const ZGetDocumentByTokenQuerySchema = z.object({
|
|
token: z.string().min(1),
|
|
});
|
|
|
|
export type TGetDocumentByTokenQuerySchema = z.infer<typeof ZGetDocumentByTokenQuerySchema>;
|
|
|
|
export const ZGetDocumentWithDetailsByIdQuerySchema = z.object({
|
|
id: z.number().min(1),
|
|
teamId: z.number().min(1).optional(),
|
|
});
|
|
|
|
export type TGetDocumentWithDetailsByIdQuerySchema = z.infer<
|
|
typeof ZGetDocumentWithDetailsByIdQuerySchema
|
|
>;
|
|
|
|
export const ZCreateDocumentMutationSchema = z.object({
|
|
title: z.string().min(1),
|
|
documentDataId: z.string().min(1),
|
|
teamId: z.number().optional(),
|
|
});
|
|
|
|
export type TCreateDocumentMutationSchema = z.infer<typeof ZCreateDocumentMutationSchema>;
|
|
|
|
export const ZSetTitleForDocumentMutationSchema = z.object({
|
|
documentId: z.number(),
|
|
teamId: z.number().min(1).optional(),
|
|
title: z.string().min(1),
|
|
});
|
|
|
|
export type TSetTitleForDocumentMutationSchema = z.infer<typeof ZSetTitleForDocumentMutationSchema>;
|
|
|
|
export const ZSetRecipientsForDocumentMutationSchema = z.object({
|
|
documentId: z.number(),
|
|
teamId: z.number().min(1).optional(),
|
|
recipients: z.array(
|
|
z.object({
|
|
id: z.number().nullish(),
|
|
email: z.string().min(1).email(),
|
|
name: z.string(),
|
|
role: z.nativeEnum(RecipientRole),
|
|
}),
|
|
),
|
|
});
|
|
|
|
export type TSetRecipientsForDocumentMutationSchema = z.infer<
|
|
typeof ZSetRecipientsForDocumentMutationSchema
|
|
>;
|
|
|
|
export const ZSetFieldsForDocumentMutationSchema = z.object({
|
|
documentId: z.number(),
|
|
fields: z.array(
|
|
z.object({
|
|
id: z.number().nullish(),
|
|
type: z.nativeEnum(FieldType),
|
|
signerEmail: z.string().min(1),
|
|
pageNumber: z.number().min(1),
|
|
pageX: z.number().min(0),
|
|
pageY: z.number().min(0),
|
|
pageWidth: z.number().min(0),
|
|
pageHeight: z.number().min(0),
|
|
}),
|
|
),
|
|
});
|
|
|
|
export type TSetFieldsForDocumentMutationSchema = z.infer<
|
|
typeof ZSetFieldsForDocumentMutationSchema
|
|
>;
|
|
|
|
export const ZSendDocumentMutationSchema = z.object({
|
|
documentId: z.number(),
|
|
teamId: z.number().optional(),
|
|
meta: z.object({
|
|
subject: z.string(),
|
|
message: z.string(),
|
|
timezone: z.string(),
|
|
dateFormat: z.string(),
|
|
redirectUrl: z
|
|
.string()
|
|
.optional()
|
|
.refine((value) => value === undefined || value === '' || URL_REGEX.test(value), {
|
|
message: 'Please enter a valid URL',
|
|
}),
|
|
}),
|
|
});
|
|
|
|
export const ZSetPasswordForDocumentMutationSchema = z.object({
|
|
documentId: z.number(),
|
|
password: z.string(),
|
|
});
|
|
|
|
export type TSetPasswordForDocumentMutationSchema = z.infer<
|
|
typeof ZSetPasswordForDocumentMutationSchema
|
|
>;
|
|
|
|
export const ZResendDocumentMutationSchema = z.object({
|
|
documentId: z.number(),
|
|
recipients: z.array(z.number()).min(1),
|
|
teamId: z.number().min(1).optional(),
|
|
});
|
|
|
|
export type TSendDocumentMutationSchema = z.infer<typeof ZSendDocumentMutationSchema>;
|
|
|
|
export const ZDeleteDraftDocumentMutationSchema = z.object({
|
|
id: z.number().min(1),
|
|
teamId: z.number().min(1).optional(),
|
|
});
|
|
|
|
export type TDeleteDraftDocumentMutationSchema = z.infer<typeof ZDeleteDraftDocumentMutationSchema>;
|
|
|
|
export const ZSearchDocumentsMutationSchema = z.object({
|
|
query: z.string(),
|
|
});
|