feat: separate document data from document

This commit is contained in:
Mythie
2023-09-07 19:27:21 +10:00
parent ff957a2f82
commit a2ef9468ae
22 changed files with 300 additions and 44 deletions

View File

@ -12,6 +12,8 @@
],
"scripts": {},
"dependencies": {
"@aws-sdk/s3-request-presigner": "^3.405.0",
"@aws-sdk/client-s3": "^3.405.0",
"@documenso/email": "*",
"@documenso/prisma": "*",
"@next-auth/prisma-adapter": "1.0.7",

View File

@ -0,0 +1,10 @@
'use server';
export type CreateDocumentOptions = {
userId: number;
fileName: string;
};
export const createDocument = () => {
//
};

View File

@ -11,5 +11,8 @@ export const getDocumentById = async ({ id, userId }: GetDocumentByIdOptions) =>
id,
userId,
},
include: {
documentData: true,
},
});
};

View File

@ -17,6 +17,7 @@ export const getDocumentAndSenderByToken = async ({
},
include: {
User: true,
documentData: true,
},
});

View File

@ -18,8 +18,15 @@ export const sealDocument = async ({ documentId }: SealDocumentOptions) => {
where: {
id: documentId,
},
include: {
documentData: true,
},
});
if (!document.documentData) {
throw new Error(`Document ${document.id} has no document data`);
}
if (document.status !== DocumentStatus.COMPLETED) {
throw new Error(`Document ${document.id} has not been completed`);
}
@ -48,7 +55,7 @@ export const sealDocument = async ({ documentId }: SealDocumentOptions) => {
}
// !: Need to write the fields onto the document as a hard copy
const { document: pdfData } = document;
const { data: pdfData } = document.documentData;
const doc = await PDFDocument.load(pdfData);
@ -64,7 +71,11 @@ export const sealDocument = async ({ documentId }: SealDocumentOptions) => {
status: DocumentStatus.COMPLETED,
},
data: {
document: Buffer.from(pdfBytes).toString('base64'),
documentData: {
update: {
data: Buffer.from(pdfBytes).toString('base64'),
},
},
},
});
};

View File

@ -0,0 +1,19 @@
-- CreateEnum
CREATE TYPE "DocumentDataType" AS ENUM ('S3_PATH', 'BYTES', 'BYTES_64');
-- CreateTable
CREATE TABLE "DocumentData" (
"id" TEXT NOT NULL,
"type" "DocumentDataType" NOT NULL,
"data" TEXT NOT NULL,
"initialData" TEXT NOT NULL,
"documentId" INTEGER NOT NULL,
CONSTRAINT "DocumentData_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "DocumentData_documentId_key" ON "DocumentData"("documentId");
-- AddForeignKey
ALTER TABLE "DocumentData" ADD CONSTRAINT "DocumentData_documentId_fkey" FOREIGN KEY ("documentId") REFERENCES "Document"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -0,0 +1,14 @@
INSERT INTO
"DocumentData" ("id", "type", "data", "initialData", "documentId") (
SELECT
CAST(gen_random_uuid() AS TEXT),
'BYTES_64',
d."document",
d."document",
d."id"
FROM
"Document" d
WHERE
d."id" IS NOT NULL
AND d."document" IS NOT NULL
);

View File

@ -0,0 +1,3 @@
-- AlterTable
ALTER TABLE "Document" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP;

View File

@ -0,0 +1,8 @@
/*
Warnings:
- You are about to drop the column `document` on the `Document` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "Document" DROP COLUMN "document";

View File

@ -85,15 +85,35 @@ enum DocumentStatus {
}
model Document {
id Int @id @default(autoincrement())
created DateTime @default(now())
userId Int
User User @relation(fields: [userId], references: [id], onDelete: Cascade)
title String
status DocumentStatus @default(DRAFT)
document String
Recipient Recipient[]
Field Field[]
id Int @id @default(autoincrement())
created DateTime @default(now())
userId Int
User User @relation(fields: [userId], references: [id], onDelete: Cascade)
title String
status DocumentStatus @default(DRAFT)
Recipient Recipient[]
Field Field[]
documentData DocumentData?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt @default(now())
}
enum DocumentDataType {
S3_PATH
BYTES
BYTES_64
}
model DocumentData {
id String @id @default(cuid())
type DocumentDataType
data String
initialData String
documentId Int
Document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
@@unique([documentId])
}
enum ReadStatus {

View File

@ -0,0 +1,5 @@
import { Document, DocumentData } from '@documenso/prisma/client';
export type DocumentWithData = Document & {
documentData?: DocumentData | null;
};

View File

@ -1,17 +1,63 @@
import { TRPCError } from '@trpc/server';
import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id';
import { getDocumentAndSenderByToken } from '@documenso/lib/server-only/document/get-document-by-token';
import { sendDocument } from '@documenso/lib/server-only/document/send-document';
import { setFieldsForDocument } from '@documenso/lib/server-only/field/set-fields-for-document';
import { setRecipientsForDocument } from '@documenso/lib/server-only/recipient/set-recipients-for-document';
import { authenticatedProcedure, router } from '../trpc';
import { authenticatedProcedure, procedure, router } from '../trpc';
import {
ZGetDocumentByIdQuerySchema,
ZGetDocumentByTokenQuerySchema,
ZSendDocumentMutationSchema,
ZSetFieldsForDocumentMutationSchema,
ZSetRecipientsForDocumentMutationSchema,
} from './schema';
export const documentRouter = router({
getDocumentById: authenticatedProcedure
.input(ZGetDocumentByIdQuerySchema)
.query(async ({ input, ctx }) => {
try {
const { id } = input;
console.log({
id,
userId: ctx.user.id,
});
return await getDocumentById({
id,
userId: ctx.user.id,
});
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to find this document. Please try again later.',
});
}
}),
getDocumentByToken: procedure.input(ZGetDocumentByTokenQuerySchema).query(async ({ input }) => {
try {
const { token } = input;
return await getDocumentAndSenderByToken({
token,
});
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to find this document. Please try again later.',
});
}
}),
setRecipientsForDocument: authenticatedProcedure
.input(ZSetRecipientsForDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {

View File

@ -2,6 +2,18 @@ import { z } from 'zod';
import { FieldType } from '@documenso/prisma/client';
export const ZGetDocumentByIdQuerySchema = z.object({
id: z.number().min(1),
});
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 ZSetRecipientsForDocumentMutationSchema = z.object({
documentId: z.number(),
recipients: z.array(

View File

@ -13,6 +13,13 @@ declare namespace NodeJS {
NEXT_PRIVATE_STRIPE_API_KEY: string;
NEXT_PRIVATE_STRIPE_WEBHOOK_SECRET: string;
NEXT_PRIVATE_UPLOAD_TRANSPORT?: 'database' | 's3';
NEXT_PRIVATE_UPLOAD_ENDPOINT?: string;
NEXT_PRIVATE_UPLOAD_REGION?: string;
NEXT_PRIVATE_UPLOAD_BUCKET?: string;
NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID?: string;
NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY?: string;
NEXT_PRIVATE_SMTP_TRANSPORT?: 'mailchannels' | 'smtp-auth' | 'smtp-api';
NEXT_PRIVATE_MAILCHANNELS_API_KEY?: string;