mirror of
https://github.com/documenso/documenso.git
synced 2025-11-14 08:42:12 +10:00
feat: migrate nextjs to rr7
This commit is contained in:
110
apps/remix/server/api/files.ts
Normal file
110
apps/remix/server/api/files.ts
Normal file
@ -0,0 +1,110 @@
|
||||
import { sValidator } from '@hono/standard-validator';
|
||||
import { Hono } from 'hono';
|
||||
import { PDFDocument } from 'pdf-lib';
|
||||
|
||||
import { APP_DOCUMENT_UPLOAD_SIZE_LIMIT } from '@documenso/lib/constants/app';
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { createDocumentData } from '@documenso/lib/server-only/document-data/create-document-data';
|
||||
import { putFileServerSide } from '@documenso/lib/universal/upload/put-file.server';
|
||||
import {
|
||||
getPresignGetUrl,
|
||||
getPresignPostUrl,
|
||||
} from '@documenso/lib/universal/upload/server-actions';
|
||||
|
||||
import type { HonoEnv } from '../router';
|
||||
import {
|
||||
type TGetPresignedGetUrlResponse,
|
||||
type TGetPresignedPostUrlResponse,
|
||||
ZGetPresignedGetUrlRequestSchema,
|
||||
ZGetPresignedPostUrlRequestSchema,
|
||||
ZUploadPdfRequestSchema,
|
||||
} from './files.types';
|
||||
|
||||
export const filesRoute = new Hono<HonoEnv>()
|
||||
/**
|
||||
* Uploads a document file to the appropriate storage location and creates
|
||||
* a document data record.
|
||||
*/
|
||||
.post('/upload-pdf', sValidator('form', ZUploadPdfRequestSchema), async (c) => {
|
||||
try {
|
||||
const { file } = c.req.valid('form');
|
||||
|
||||
if (!file) {
|
||||
return c.json({ error: 'No file provided' }, 400);
|
||||
}
|
||||
|
||||
// Todo: Do we want to validate the file type?
|
||||
// if (file.type !== 'application/pdf') {
|
||||
// return c.json({ error: 'File must be a PDF' }, 400);
|
||||
// }
|
||||
|
||||
// Todo: This is new.
|
||||
// Add file size validation.
|
||||
// Convert MB to bytes (1 MB = 1024 * 1024 bytes)
|
||||
const MAX_FILE_SIZE = APP_DOCUMENT_UPLOAD_SIZE_LIMIT * 1024 * 1024;
|
||||
|
||||
if (file.size > MAX_FILE_SIZE) {
|
||||
return c.json({ error: 'File too large' }, 400);
|
||||
}
|
||||
|
||||
const arrayBuffer = await file.arrayBuffer();
|
||||
|
||||
const pdf = await PDFDocument.load(arrayBuffer).catch((e) => {
|
||||
console.error(`PDF upload parse error: ${e.message}`);
|
||||
|
||||
throw new AppError('INVALID_DOCUMENT_FILE');
|
||||
});
|
||||
|
||||
if (pdf.isEncrypted) {
|
||||
throw new AppError('INVALID_DOCUMENT_FILE');
|
||||
}
|
||||
|
||||
// Todo: Test this.
|
||||
if (!file.name.endsWith('.pdf')) {
|
||||
Object.defineProperty(file, 'name', {
|
||||
writable: true,
|
||||
value: `${file.name}.pdf`,
|
||||
});
|
||||
}
|
||||
|
||||
const { type, data } = await putFileServerSide(file);
|
||||
|
||||
const result = await createDocumentData({ type, data });
|
||||
|
||||
return c.json(result);
|
||||
} catch (error) {
|
||||
console.error('Upload failed:', error);
|
||||
return c.json({ error: 'Upload failed' }, 500);
|
||||
}
|
||||
})
|
||||
.post('/presigned-get-url', sValidator('json', ZGetPresignedGetUrlRequestSchema), async (c) => {
|
||||
const { key } = await c.req.json();
|
||||
console.log(key);
|
||||
|
||||
try {
|
||||
const { url } = await getPresignGetUrl(key || '');
|
||||
|
||||
return c.json({ url } satisfies TGetPresignedGetUrlResponse);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new AppError(AppErrorCode.UNKNOWN_ERROR);
|
||||
}
|
||||
})
|
||||
.post('/presigned-post-url', sValidator('json', ZGetPresignedPostUrlRequestSchema), async (c) => {
|
||||
const { fileName, contentType } = c.req.valid('json');
|
||||
|
||||
try {
|
||||
console.log({
|
||||
fileName,
|
||||
});
|
||||
const { key, url } = await getPresignPostUrl(fileName, contentType);
|
||||
console.log(key);
|
||||
|
||||
return c.json({ key, url } satisfies TGetPresignedPostUrlResponse);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new AppError(AppErrorCode.UNKNOWN_ERROR);
|
||||
}
|
||||
});
|
||||
38
apps/remix/server/api/files.types.ts
Normal file
38
apps/remix/server/api/files.types.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import DocumentDataSchema from '@documenso/prisma/generated/zod/modelSchema/DocumentDataSchema';
|
||||
|
||||
export const ZUploadPdfRequestSchema = z.object({
|
||||
file: z.instanceof(File),
|
||||
});
|
||||
|
||||
export const ZUploadPdfResponseSchema = DocumentDataSchema.pick({
|
||||
type: true,
|
||||
id: true,
|
||||
});
|
||||
|
||||
export type TUploadPdfRequest = z.infer<typeof ZUploadPdfRequestSchema>;
|
||||
export type TUploadPdfResponse = z.infer<typeof ZUploadPdfResponseSchema>;
|
||||
|
||||
export const ZGetPresignedPostUrlRequestSchema = z.object({
|
||||
fileName: z.string().min(1),
|
||||
contentType: z.string().min(1),
|
||||
});
|
||||
|
||||
export const ZGetPresignedPostUrlResponseSchema = z.object({
|
||||
key: z.string().min(1),
|
||||
url: z.string().min(1),
|
||||
});
|
||||
|
||||
export const ZGetPresignedGetUrlRequestSchema = z.object({
|
||||
key: z.string().min(1),
|
||||
});
|
||||
|
||||
export const ZGetPresignedGetUrlResponseSchema = z.object({
|
||||
url: z.string().min(1),
|
||||
});
|
||||
|
||||
export type TGetPresignedPostUrlRequest = z.infer<typeof ZGetPresignedPostUrlRequestSchema>;
|
||||
export type TGetPresignedPostUrlResponse = z.infer<typeof ZGetPresignedPostUrlResponseSchema>;
|
||||
export type TGetPresignedGetUrlRequest = z.infer<typeof ZGetPresignedGetUrlRequestSchema>;
|
||||
export type TGetPresignedGetUrlResponse = z.infer<typeof ZGetPresignedGetUrlResponseSchema>;
|
||||
Reference in New Issue
Block a user