-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add route handler, content type validator
- Loading branch information
1 parent
98edd2e
commit b262737
Showing
30 changed files
with
531 additions
and
198 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ | |
"uplo" | ||
], | ||
"cSpell.ignoreWords": [ | ||
"Hono", | ||
"Nextra", | ||
"blurhash", | ||
"tsup" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,92 +1,42 @@ | ||
import Uplo, { BlobInput, blobStringInput } from '@uplo/server'; | ||
import S3Service from '@uplo/service-s3'; | ||
import { DrizzleAdapter } from '@uplo/adapter-drizzle-pg'; | ||
import { initDB, schema } from './db'; | ||
import { checksumString } from '@uplo/utils'; | ||
// import GCSService from '@uplo/service-gcs' | ||
|
||
export interface Env { | ||
AWS_ENDPOINT: string; | ||
AWS_BUCKET: string; | ||
AWS_ACCESS_KEY_ID: string; | ||
AWS_SECRET_ACCESS_KEY: string; | ||
DATABASE_URL: string; | ||
// Example binding to R2. Learn more at https://developers.cloudflare.com/workers/runtime-apis/r2/ | ||
// MY_BUCKET: R2Bucket; | ||
// | ||
// Example binding to a Service. Learn more at https://developers.cloudflare.com/workers/runtime-apis/service-bindings/ | ||
// MY_SERVICE: Fetcher; | ||
} | ||
import { Hono } from 'hono'; | ||
import { dbMiddleware } from './middleware/dbMiddleware.js'; | ||
import { uploMiddleware } from './middleware/uploMiddleware.js'; | ||
import type { HonoEnv } from './types/hono.js'; | ||
import { imageUrlToBlobInput } from './utils/imageUrlToBlobInput.js'; | ||
import { createUploRouteHandler } from '@uplo/server/route-handler'; | ||
|
||
const imageUrlToBlobInput = async (url: string): Promise<BlobInput> => { | ||
const data = await fetch(url); | ||
const arrayBuffer = await data.arrayBuffer(); | ||
const content = new Uint8Array(arrayBuffer); | ||
// const base64 = btoa(String.fromCharCode()); | ||
const contentType = data.headers.get('content-type'); | ||
const app = new Hono<HonoEnv>(); | ||
|
||
if (!contentType) { | ||
throw new Error('Cannot get content type from image'); | ||
} | ||
app.use(dbMiddleware); | ||
app.use(uploMiddleware); | ||
|
||
return { | ||
fileName: 'image.jpg', | ||
size: content.length, | ||
contentType, | ||
checksum: await checksumString(content), | ||
content: content, | ||
}; | ||
}; | ||
app.get('/', (c) => c.text('Welcome to Uplo!')); | ||
|
||
export default { | ||
async fetch( | ||
request: Request, | ||
env: Env, | ||
ctx: ExecutionContext | ||
): Promise<Response> { | ||
const { db } = await initDB({ | ||
databaseUrl: env.DATABASE_URL, | ||
}); | ||
app.post('/attach-avatar', async (c) => { | ||
const blobInput = await imageUrlToBlobInput( | ||
'https://www.viewbug.com/media/mediafiles/2015/10/16/59560665_medium.jpg' | ||
); | ||
await c.get('uplo').attachments.user(1).avatar.attachFile(blobInput); | ||
|
||
const s3Service = S3Service({ | ||
isPublic: false, | ||
bucket: env.AWS_BUCKET, | ||
accessKeyId: env.AWS_ACCESS_KEY_ID, | ||
secretAccessKey: env.AWS_SECRET_ACCESS_KEY, | ||
endpoint: env.AWS_ENDPOINT, | ||
forcePathStyle: true, | ||
requestHandler: { | ||
requestInit(_httpRequest) { | ||
return { cache: undefined }; | ||
}, | ||
}, | ||
}); | ||
return c.json({ success: true, message: 'Avatar attached' }); | ||
}); | ||
|
||
const uplo = Uplo({ | ||
adapter: DrizzleAdapter({ | ||
db, | ||
schema, | ||
}), | ||
services: { | ||
s3: s3Service, | ||
}, | ||
attachments: { | ||
user: { | ||
avatar: true, | ||
}, | ||
}, | ||
}); | ||
app.get('/avatar-url', async (c) => { | ||
const uplo = c.get('uplo'); | ||
|
||
// const service = GCSService({}) | ||
const userAttachment = await uplo.attachments.user(1).avatar.findOne(); | ||
|
||
// const blobInput = await imageUrlToBlobInput( | ||
// 'https://www.viewbug.com/media/mediafiles/2015/10/16/59560665_medium.jpg' | ||
// ); | ||
// await uplo.attachments.user(1).avatar.attachFile(blobInput); | ||
const avatarUrl = await userAttachment?.url(); | ||
return c.json({ avatarUrl }); | ||
}); | ||
|
||
const userAttachment = await uplo.attachments.user(1).avatar.findOne(); | ||
app.all('/uplo/*', async (c) => { | ||
const uplo = c.get('uplo'); | ||
const handler = createUploRouteHandler({ uplo }); | ||
|
||
const avatarUrl = await userAttachment?.url(); | ||
return new Response(`User avatar url: ${avatarUrl}`); | ||
}, | ||
}; | ||
return handler(c.req.raw); | ||
}); | ||
|
||
export default app; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { createMiddleware } from 'hono/factory'; | ||
import { initDB } from '../db/initDB.js'; | ||
import { HonoEnv } from '../types/hono.js'; | ||
|
||
export const dbMiddleware = createMiddleware<HonoEnv>(async (c, next) => { | ||
const { db } = await initDB({ | ||
databaseUrl: c.env.DATABASE_URL, | ||
}); | ||
|
||
c.set('db', db); | ||
|
||
await next(); | ||
}); |
10 changes: 10 additions & 0 deletions
10
examples/cloudflare-worker/src/middleware/uploMiddleware.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { createMiddleware } from 'hono/factory'; | ||
import { HonoEnv } from '../types/hono.js'; | ||
import { createUplo } from '../services/uplo.js'; | ||
|
||
export const uploMiddleware = createMiddleware<HonoEnv>(async (c, next) => { | ||
const uplo = createUplo(c); | ||
|
||
c.set('uplo', uplo); | ||
await next(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import Uplo from '@uplo/server'; | ||
import S3Service from '@uplo/service-s3'; | ||
import { DrizzleAdapter } from '@uplo/adapter-drizzle-pg'; | ||
import type { HonoContext } from '../types/hono.js'; | ||
import * as schema from '../db/schema.js'; | ||
|
||
export const createUplo = (c: HonoContext) => { | ||
const db = c.get('db'); | ||
|
||
const s3Service = S3Service({ | ||
isPublic: false, | ||
bucket: c.env.AWS_BUCKET, | ||
accessKeyId: c.env.AWS_ACCESS_KEY_ID, | ||
secretAccessKey: c.env.AWS_SECRET_ACCESS_KEY, | ||
endpoint: c.env.AWS_ENDPOINT, | ||
requestHandler: { | ||
requestInit(_httpRequest: Request) { | ||
return { cache: undefined }; | ||
}, | ||
}, | ||
}); | ||
|
||
const uplo = Uplo({ | ||
config: { | ||
privateKey: c.env.UPLO_SECRET_TOKEN, | ||
}, | ||
adapter: DrizzleAdapter({ | ||
db, | ||
schema, | ||
}), | ||
services: { | ||
s3: s3Service, | ||
}, | ||
attachments: { | ||
user: { | ||
avatar: { | ||
validate: { | ||
// contentType: ['image/png', 'image/jpeg'], | ||
contentType: /image\/\w/, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}); | ||
|
||
return uplo; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import type { Hono as H, Context } from 'hono'; | ||
import type { initDB } from '../db/initDB.js'; | ||
import type { createUplo } from '../services/uplo.js'; | ||
|
||
export type HonoBindings = { | ||
DATABASE_URL: string; | ||
UPLO_SECRET_TOKEN: string; | ||
|
||
AWS_BUCKET: string; | ||
AWS_ACCESS_KEY_ID: string; | ||
AWS_SECRET_ACCESS_KEY: string; | ||
AWS_ENDPOINT: string; | ||
}; | ||
|
||
export type HonoVariables = { | ||
db: Awaited<ReturnType<typeof initDB>>['db']; | ||
uplo: Awaited<ReturnType<typeof createUplo>>; | ||
}; | ||
|
||
export type HonoEnv = { | ||
Bindings: HonoBindings; | ||
Variables: HonoVariables; | ||
}; | ||
|
||
export type Hono = H<HonoEnv>; | ||
export type HonoContext = Context<HonoEnv>; |
22 changes: 22 additions & 0 deletions
22
examples/cloudflare-worker/src/utils/imageUrlToBlobInput.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { BlobInput } from '@uplo/server'; | ||
import { checksumString } from '@uplo/utils'; | ||
|
||
export const imageUrlToBlobInput = async (url: string): Promise<BlobInput> => { | ||
const data = await fetch(url); | ||
const arrayBuffer = await data.arrayBuffer(); | ||
const content = new Uint8Array(arrayBuffer); | ||
// const base64 = btoa(String.fromCharCode()); | ||
const contentType = data.headers.get('content-type'); | ||
|
||
if (!contentType) { | ||
throw new Error('Cannot get content type from image'); | ||
} | ||
|
||
return { | ||
fileName: 'image.jpg', | ||
size: content.length, | ||
contentType, | ||
checksum: await checksumString(content), | ||
content: content, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.