mirror of
https://github.com/get-drexa/drive.git
synced 2025-11-30 21:41:39 +00:00
feat: initial impl of file proxy
This commit is contained in:
4
apps/file-proxy/.env.sample
Normal file
4
apps/file-proxy/.env.sample
Normal file
@@ -0,0 +1,4 @@
|
||||
CONVEX_URL=
|
||||
# api key used to auth with the convex backend
|
||||
# use the drexa cli to generate an api key, then add the api key to the api key table via the convex dashboard
|
||||
API_KEY=
|
||||
14
apps/file-proxy/auth.ts
Normal file
14
apps/file-proxy/auth.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { createMiddleware } from "hono/factory"
|
||||
|
||||
export type ApiKeyContextVariable = {
|
||||
apiKey: string
|
||||
}
|
||||
|
||||
const apiKeyMiddleware = createMiddleware<{ Variables: ApiKeyContextVariable }>(
|
||||
async (c, next) => {
|
||||
c.set("apiKey", process.env.API_KEY)
|
||||
await next()
|
||||
},
|
||||
)
|
||||
|
||||
export { apiKeyMiddleware }
|
||||
@@ -0,0 +1,16 @@
|
||||
import { ConvexHttpClient } from "convex/browser"
|
||||
import { createMiddleware } from "hono/factory"
|
||||
|
||||
const _client = new ConvexHttpClient(process.env.CONVEX_URL)
|
||||
|
||||
export type ConvexContextVariables = {
|
||||
convex: ConvexHttpClient
|
||||
}
|
||||
|
||||
export const convexMiddleware = createMiddleware<{
|
||||
Variables: ConvexContextVariables
|
||||
}>(async (c, next) => {
|
||||
c.var
|
||||
c.set("convex", _client)
|
||||
await next()
|
||||
})
|
||||
|
||||
6
apps/file-proxy/env.d.ts
vendored
Normal file
6
apps/file-proxy/env.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
declare module "bun" {
|
||||
interface Env {
|
||||
CONVEX_URL: string
|
||||
API_KEY: string
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,39 @@
|
||||
import { Hono } from "hono"
|
||||
import { api } from "@fileone/convex/api"
|
||||
import { newRouter } from "./router"
|
||||
|
||||
const h = new Hono().basePath("/files")
|
||||
const r = newRouter().basePath("/files")
|
||||
|
||||
h.get("/:fileId", async (c) => {
|
||||
const fileId = c.req.param("fileId")
|
||||
if (!fileId) {
|
||||
return c.json({ error: "File ID is required" }, 400)
|
||||
r.get(":shareToken", async (c) => {
|
||||
const shareToken = c.req.param("shareToken")
|
||||
if (!shareToken) {
|
||||
return c.json({ error: "not found" }, 404)
|
||||
}
|
||||
|
||||
const fileShare = await c.var.convex.query(api.fileshare.findFileShare, {
|
||||
apiKey: c.var.apiKey,
|
||||
shareToken,
|
||||
})
|
||||
if (!fileShare) {
|
||||
return c.json({ error: "not found" }, 404)
|
||||
}
|
||||
|
||||
const fileUrl = await c.var.convex.query(api.filesystem.getStorageUrl, {
|
||||
apiKey: c.var.apiKey,
|
||||
storageId: fileShare.storageId,
|
||||
})
|
||||
if (!fileUrl) {
|
||||
return c.json({ error: "not found" }, 404)
|
||||
}
|
||||
|
||||
const fileResponse = await fetch(fileUrl)
|
||||
if (!fileResponse.ok) {
|
||||
return c.json({ error: "not found" }, 404)
|
||||
}
|
||||
|
||||
return new Response(fileResponse.body, {
|
||||
status: fileResponse.status,
|
||||
headers: fileResponse.headers,
|
||||
})
|
||||
})
|
||||
|
||||
export { h as files }
|
||||
export { r as files }
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import { Hono } from "hono"
|
||||
import { handleFileRequest } from "./files"
|
||||
import { apiKeyMiddleware } from "./auth"
|
||||
import { convexMiddleware } from "./convex"
|
||||
import { files } from "./files"
|
||||
|
||||
Bun.serve({
|
||||
routes: {
|
||||
"/files/:fileId": {
|
||||
GET: handleFileRequest,
|
||||
},
|
||||
},
|
||||
})
|
||||
const app = new Hono()
|
||||
|
||||
app.use(convexMiddleware)
|
||||
app.use(apiKeyMiddleware)
|
||||
|
||||
app.route("/", files)
|
||||
|
||||
export default {
|
||||
port: 8081,
|
||||
fetch: app.fetch,
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "bun --hot run index.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
},
|
||||
@@ -11,6 +14,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@fileone/convex": "workspace:*",
|
||||
"arktype": "^2.1.23",
|
||||
"convex": "^1.28.0",
|
||||
"hono": "^4.10.1"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import type { RouterTypes } from "bun"
|
||||
import { Hono } from "hono"
|
||||
import type { ApiKeyContextVariable } from "./auth"
|
||||
import type { ConvexContextVariables } from "./convex"
|
||||
|
||||
function router<
|
||||
R extends { [K in keyof R]: RouterTypes.RouteValue<Extract<K, string>> },
|
||||
>(routes: R): R {
|
||||
return routes
|
||||
type ContextVariables = ConvexContextVariables & ApiKeyContextVariable
|
||||
|
||||
export function newRouter() {
|
||||
return new Hono<{
|
||||
Variables: ContextVariables
|
||||
}>()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user