diff --git a/.gitignore b/.gitignore
index bfc7379..2a4510c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -40,3 +40,5 @@ next-env.d.ts
/.next
/.vscode
/src/pages/api/legacy/
+
+.vercel
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..1a2fb33
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TODO.md b/TODO.md
index 8630db6..3f02df2 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,3 +1,5 @@
+- Redo how to handle error
+
# /
- ~~Override opengraph using banner image~~
- ~~Render readme file~~
diff --git a/package.json b/package.json
index 046370c..4c98133 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
"googleapis": "^118.0.0",
"jsonwebtoken": "^9.0.0",
"mime-types": "^2.1.35",
- "next": "^13.4.3",
+ "next": "^13.4.4",
"next-seo": "^6.0.0",
"nextjs-progressbar": "^0.0.16",
"postcss": "8.4.22",
diff --git a/src/app/(api)/api/banner/[encryptedFileId]/route.ts b/src/app/(api)/api/banner/[encryptedFileId]/route.ts
index e69de29..7652871 100644
--- a/src/app/(api)/api/banner/[encryptedFileId]/route.ts
+++ b/src/app/(api)/api/banner/[encryptedFileId]/route.ts
@@ -0,0 +1,82 @@
+import { NextRequest, NextResponse } from "next/server";
+
+import createErrorPayload from "utils/apiHelper/createErrorPayload";
+import gdrive from "utils/apiHelper/gdrive";
+import shortEncryption from "utils/encryptionHelper/shortEncryption";
+import ExtendedError from "utils/generalHelper/extendedError";
+
+import { Constant } from "types/general/constant";
+
+import apiConfig from "config/api.config";
+
+export async function GET(
+ request: NextRequest,
+ { params }: { params: { encryptedFileId: string } },
+) {
+ const _start = Date.now();
+ const { encryptedFileId } = params;
+
+ try {
+ const getMetadata = gdrive.files.get({
+ fileId: shortEncryption.decrypt(encryptedFileId),
+ fields: "id, name, mimeType, webContentLink",
+ });
+ const getStream = gdrive.files.get(
+ {
+ fileId: shortEncryption.decrypt(encryptedFileId),
+ alt: "media",
+ },
+ { responseType: "arraybuffer" },
+ );
+
+ const [metadata, stream] = await Promise.all([
+ getMetadata,
+ getStream,
+ ]);
+
+ if (!metadata || metadata.data.trashed) {
+ throw new ExtendedError(
+ Constant.apiFileNotFound,
+ 404,
+ "notFound",
+ Constant.reasonNotFound,
+ );
+ }
+
+ if (
+ Number(metadata.data.size) >
+ apiConfig.files.download.maxFileSize &&
+ apiConfig.files.download.maxFileSize > 0
+ ) {
+ return NextResponse.redirect(
+ metadata.data.webContentLink as string,
+ {
+ status: 302,
+ },
+ );
+ }
+
+ const imgBuffer = (await stream.data) as ArrayBuffer;
+
+ return new NextResponse(imgBuffer, {
+ status: 200,
+ headers: {
+ "Content-Type":
+ metadata.data.mimeType ||
+ "application/octet-stream",
+ "Cache-Control": apiConfig.cacheControl,
+ "Content-Disposition": `inline; filename="${metadata.data.name}"`,
+ },
+ });
+ } catch (error: any) {
+ const payload = createErrorPayload(
+ error,
+ "GET /api/banner/:id",
+ _start,
+ );
+
+ return NextResponse.json(payload, {
+ status: payload.code,
+ });
+ }
+}
diff --git a/src/app/(api)/api/files/[encryptedId]/route.ts b/src/app/(api)/api/files/[encryptedId]/route.ts
index 13fd8e0..ab6e9af 100644
--- a/src/app/(api)/api/files/[encryptedId]/route.ts
+++ b/src/app/(api)/api/files/[encryptedId]/route.ts
@@ -45,78 +45,28 @@ export async function GET(
});
if (!file || file.data.trashed) {
- const msg = file.data.trashed
- ? "File has been deleted"
- : "File not found";
throw new ExtendedError(
Constant.apiFileNotFound,
404,
"notFound",
- msg,
+ Constant.reasonNotFound,
);
}
+ /**
+ * If fetched file isn't a folder, return File
+ */
if (
file.data.mimeType !==
"application/vnd.google-apps.folder"
) {
if (thumbnail === "1") {
- if (!file.data.thumbnailLink) {
- const imgStream = await fetch(
- `${apiConfig.basePath}/og.png`,
- ).then((res) => res.arrayBuffer());
- return new NextResponse(imgStream, {
- status: 200,
- });
- }
- if (file.data.mimeType?.startsWith("image/")) {
- const imgStream = await gdrive.files.get(
- {
- fileId: id,
- alt: "media",
- },
- { responseType: "stream" },
- );
- if (
- Number(file.data.size) <
- apiConfig.files.download.maxFileSize &&
- apiConfig.files.download.maxFileSize > 0
- ) {
- const arrayBuffer =
- await new Promise(
- (resolve, reject) => {
- const chunks: Buffer[] = [];
- imgStream.data.on("data", (chunk) =>
- chunks.push(chunk),
- );
- imgStream.data.on("end", () => {
- const buffer = Buffer.concat(chunks);
- resolve(
- buffer.buffer.slice(
- buffer.byteOffset,
- buffer.byteOffset +
- buffer.byteLength,
- ),
- );
- });
- imgStream.data.on("error", reject);
- },
- );
- return new NextResponse(arrayBuffer, {
- status: 200,
- headers: {
- "Content-Type":
- file.data.mimeType ||
- "application/octet-stream",
- "Cache-Control": apiConfig.cacheControl,
- "Content-Disposition": `inline; filename="${file.data.name}"`,
- },
- });
- }
- }
-
return NextResponse.redirect(
- file.data.thumbnailLink as string,
+ `${
+ apiConfig.basePath
+ }/api/thumbnail/${shortEncryption.encrypt(
+ id as string,
+ )}`,
{
status: 302,
},
@@ -148,9 +98,8 @@ export async function GET(
}
const query = [
+ ...apiConfig.files.query,
`'${id}' in parents`,
- "trashed = false",
- "'me' in owners",
];
const fetchFolderContents = await gdrive.files.list({
q: `${query.join(" and ")}`,
@@ -195,7 +144,7 @@ export async function GET(
return NextResponse.redirect(
`${
apiConfig.basePath
- }/api/banner?id=${shortEncryption.encrypt(
+ }/api/banner/${shortEncryption.encrypt(
bannerFile.id as string,
)}`,
{
@@ -263,7 +212,7 @@ export async function GET(
} catch (error: any) {
const payload = createErrorPayload(
error,
- "GET /api/files",
+ "GET /api/files/:id",
_start,
);
diff --git a/src/app/(api)/api/files/route.ts b/src/app/(api)/api/files/route.ts
index 84f718d..cc445bd 100644
--- a/src/app/(api)/api/files/route.ts
+++ b/src/app/(api)/api/files/route.ts
@@ -23,9 +23,8 @@ export async function GET(request: NextRequest) {
);
const query: string[] = [
- "trashed = false",
- "'me' in owners",
- `parents = '${apiConfig.files.rootFolder}'`,
+ ...apiConfig.files.query,
+ `'${apiConfig.files.rootFolder}' in parents`,
];
const fetchFolderContents = await gdrive.files.list({
q: `${query.join(" and ")}`,
@@ -70,7 +69,7 @@ export async function GET(request: NextRequest) {
return NextResponse.redirect(
`${
apiConfig.basePath
- }/api/banner?id=${shortEncryption.encrypt(
+ }/api/banner/${shortEncryption.encrypt(
bannerFile.id as string,
)}`,
{
diff --git a/src/app/(api)/api/thumbnail/[encryptedFileId]/route.ts b/src/app/(api)/api/thumbnail/[encryptedFileId]/route.ts
index e69de29..fbcd578 100644
--- a/src/app/(api)/api/thumbnail/[encryptedFileId]/route.ts
+++ b/src/app/(api)/api/thumbnail/[encryptedFileId]/route.ts
@@ -0,0 +1,103 @@
+import { NextRequest, NextResponse } from "next/server";
+
+import createErrorPayload from "utils/apiHelper/createErrorPayload";
+import gdrive from "utils/apiHelper/gdrive";
+import shortEncryption from "utils/encryptionHelper/shortEncryption";
+import ExtendedError from "utils/generalHelper/extendedError";
+
+import { Constant } from "types/general/constant";
+
+import apiConfig from "config/api.config";
+
+export async function GET(
+ request: NextRequest,
+ { params }: { params: { encryptedFileId: string } },
+) {
+ const _start = Date.now();
+ const { encryptedFileId } = params;
+
+ try {
+ const getMetadata = gdrive.files.get({
+ fileId: shortEncryption.decrypt(encryptedFileId),
+ fields:
+ "id, name, mimeType, webContentLink, thumbnailLink, size",
+ });
+ const getStream = gdrive.files.get(
+ {
+ fileId: shortEncryption.decrypt(encryptedFileId),
+ alt: "media",
+ },
+ { responseType: "arraybuffer" },
+ );
+
+ const [metadata, stream] = await Promise.all([
+ getMetadata,
+ getStream,
+ ]);
+
+ if (!metadata || metadata.data.trashed) {
+ throw new ExtendedError(
+ Constant.apiFileNotFound,
+ 404,
+ "notFound",
+ Constant.reasonNotFound,
+ );
+ }
+
+ if (!metadata.data.thumbnailLink) {
+ const imgStream = await fetch(
+ `${apiConfig.basePath}/og.png`,
+ ).then((res) => res.arrayBuffer());
+
+ return new NextResponse(imgStream, {
+ status: 200,
+ headers: {
+ "Content-Type":
+ metadata.data.mimeType ||
+ "application/octet-stream",
+ "Cache-Control": apiConfig.cacheControl,
+ "Content-Disposition": `inline; filename="${metadata.data.name}"`,
+ },
+ });
+ }
+
+ const isWithinMaxFileSize =
+ Number(metadata.data.size) <
+ apiConfig.files.download.maxFileSize &&
+ apiConfig.files.download.maxFileSize > 0;
+
+ if (
+ metadata.data.mimeType?.startsWith("image") &&
+ isWithinMaxFileSize
+ ) {
+ const imgBuffer = (await stream.data) as ArrayBuffer;
+
+ return new NextResponse(imgBuffer, {
+ status: 200,
+ headers: {
+ "Cache-Control": apiConfig.cacheControl,
+ },
+ });
+ }
+
+ return NextResponse.redirect(
+ metadata.data.thumbnailLink as string,
+ {
+ status: 302,
+ headers: {
+ "Cache-Control": apiConfig.cacheControl,
+ },
+ },
+ );
+ } catch (error: any) {
+ const payload = createErrorPayload(
+ error,
+ "GET /api/thumbnail/:id",
+ _start,
+ );
+
+ return NextResponse.json(payload, {
+ status: payload.code,
+ });
+ }
+}
diff --git a/src/app/[...path]/page.tsx b/src/app/[...path]/page.tsx
index af8911f..4e0cfdc 100644
--- a/src/app/[...path]/page.tsx
+++ b/src/app/[...path]/page.tsx
@@ -120,7 +120,6 @@ async function FilePage({ params }: Props) {
if (!pathValidation.success) {
const errorData = pathValidation as API_Error;
- console.error(errorData);
const payload = handleError(errorData);
throw new Error(payload);
}
diff --git a/src/app/error.tsx b/src/app/error.tsx
index fac58bc..c678541 100644
--- a/src/app/error.tsx
+++ b/src/app/error.tsx
@@ -24,24 +24,23 @@ export default function Error({
const [path, setPath] = useState("root");
useEffect(() => {
- console.log("CHECKPOINT ERROR PAGE", error);
if (error.message.includes("{")) {
- console.log("CHECKPOINT ERROR MESSAGE IS JSON");
const errorObj = JSON.parse(
error.message,
) as ExtendedError;
const extendError = new ExtendedError(
- errorObj.extendedMessage ||
+ errorObj.extendedMessage ??
Constant.apiInternalError,
- errorObj.code || 500,
- errorObj.category || "internalServerError",
- errorObj.reason || "Internal Server Error",
+ errorObj.code ?? 500,
+ errorObj.category ?? "internalServerError",
+ errorObj.reason ?? "Internal Server Error",
);
- console.log("CHECKPOINT EXTENDED ERROR", extendError);
setExtendedError(extendError);
+ console.log(extendError.code);
+
const path =
- extendError.reason?.split('"')[1].split('"')[0] ||
+ extendError.reason?.split('"')[1]?.split('"')[0] ??
"root";
setPath(path);
} else {
@@ -55,14 +54,14 @@ export default function Error({
}
}, [error]);
- useEffect(() => {
- if (extendedError?.code === 401) {
- router.push(
- `/password?redirect=${pathname}&path=${path}`,
- );
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [extendedError, path, pathname]);
+ // useEffect(() => {
+ // if (extendedError?.code === 401) {
+ // router.push(
+ // `/password?redirect=${pathname}&path=${path}`,
+ // );
+ // }
+ // // eslint-disable-next-line react-hooks/exhaustive-deps
+ // }, [extendedError, path, pathname]);
return (
);
}
diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx
index 89048af..fe138f8 100644
--- a/src/app/not-found.tsx
+++ b/src/app/not-found.tsx
@@ -1,7 +1,6 @@
import Link from "next/link";
function NotFound() {
- console.log("Not Found");
return (