Skip to content

Commit

Permalink
docs: update blob + miscellanous
Browse files Browse the repository at this point in the history
  • Loading branch information
smarroufin committed Feb 21, 2024
1 parent e7ffed1 commit 1c98fd7
Show file tree
Hide file tree
Showing 7 changed files with 227 additions and 4 deletions.
14 changes: 12 additions & 2 deletions docs/content/2.usage/1.database.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ NuxtHub Database is a layer to [Cloudflare D1](https://developers.cloudflare.com

<!-- TODO: config, binding ? -->

Once properly configured, NuxtHub module exposes a server composable to your application.
Once properly configured, NuxtHub module exposes a server composable to the application.

## `useDB()`
## `useDatabase()`

Server composable that returns a set of methods from [D1Database](https://developers.cloudflare.com/d1/build-databases/query-databases/).

### `exec()`

### `dump()`

### `prepare()`

### `batch()`
8 changes: 8 additions & 0 deletions docs/content/2.usage/2.kv.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,11 @@ description: How to use key-value data storage with NuxtHub.
---

NuxtHub KV is a layer to [Cloudflare Workers KV](https://developers.cloudflare.com/kv), a global, low-latency, key-value data storage.

<!-- TODO: config, binding ? -->

Once properly configured, NuxtHub module exposes a server composable to the application.

## `useKV()`

Server composable that returns a [Storage](https://unstorage.unjs.io/getting-started/usage#interface).
172 changes: 172 additions & 0 deletions docs/content/2.usage/3.blob.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,175 @@ description: How to store objects with NuxtHub.
---

NuxtHub Blob is a layer to [Cloudflare R2](https://developers.cloudflare.com/r2), allowing to store large amounts of unstructured data.

<!-- TODO: config, binding ? -->

Once properly configured, NuxtHub module exposes a server composable to the application.

## `useBlob()`

Server composable that returns a set of methods to manipulate the blob storage.

### `list()`

Returns a paginated list of blobs.

```ts[/api/blob/index.get.ts]
export default eventHandler(async () => {
return useBlob().list()
})
```

#### Params

- `options`: [`BlobListOptions`](#bloblistoptions)

#### Return

Returns an array of [`BlobObject`](#blobobject).

### `serve()`

Returns a blob's data.

```ts[/api/blob/[...pathname\\].get.ts]
export default eventHandler(async (event) => {
const { pathname } = getRouterParams(event)
return useBlob().serve(event, pathname)
})
```

#### Params

- `event`: [`H3Event`](https://github.com/unjs/h3)
- `pathname`: `string`

#### Return

Returns the blob's raw data and sets `Content-Type` and `Content-Length` headers.

::callout{icon="i-heroicons-information-circle"}
If you are fetching an image with a server route similar to the one above, you might simply want to use it this way:
<br>
```vue
<img :src="`/api/blob/${file.pathname}`">
```
::

### `head()`

Returns a blob's metadata.

```ts[/api/blob/[...pathname\\].head.ts]
export default eventHandler(async (event) => {
const { pathname } = getRouterParams(event)
const blob = await useBlob().head(pathname)
setHeader(event, 'x-blob', JSON.stringify(blob))
return sendNoContent(event)
})
```

#### Params

- `pathname`: `string`

#### Return

Returns a [`BlobObject`](#blobobject).

### `put()`

Uploads a blob.

```ts[/api/blob/[...pathname\\].put.ts]
export default eventHandler(async (event) => {
const { pathname } = getRouterParams(event)
const form = await readFormData(event)
const file = form.get('file') as Blob
if (!file || !file.size) {
throw createError({ statusCode: 400, message: 'No file provided' })
}
ensureBlob(file, { maxSize: '1MB', types: ['image' ]})
return useBlob().put(`images/${file.name}`, file, { addRandomSuffix: false })
})
```

#### Params

- `pathname`: `string`
- `body`: `string` | `ReadableStream<any>` | `ArrayBuffer` | `ArrayBufferView` | `Blob`
- `options`: [`BlobPutOptions`](#blobputoptions)
#### Return

Returns a [`BlobObject`](#blobobject).

::callout{icon="i-heroicons-light-bulb"}
Take a look at all the [validation](/recipes/validation) utils like [`ensureBlob`](/recipes/validation#ensureblob)
::

### `delete()`

Deletes a blob.

```ts[/api/blob/[...pathname\\].delete.ts]
export default eventHandler(async (event) => {
const { pathname } = getRouterParams(event)
await useBlob().delete(pathname)
return sendNoContent(event)
})
```

#### Params

- `pathname`: `string`

#### Return

Returns nothing.

## Types

### `BlobListOptions`

```ts
interface BlobListOptions {
/**
* The maximum number of blobs to return per request.
* @default 1000
*/
limit?: number
prefix?: string
cursor?: string
}
```

### `BlobPutOptions`

```ts
interface BlobPutOptions {
contentType?: string,
contentLength?: string,
addRandomSuffix?: boolean,
[key: string]: any
}
```

### `BlobObject`

```ts
interface BlobObject {
pathname: string
contentType: string | undefined
size: number
uploadedAt: Date
}
```
6 changes: 6 additions & 0 deletions docs/content/2.usage/4.analytics.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,9 @@ description: How to track events with NuxtHub.
---

NuxtHub Analytics is a layer to [Cloudflare Workers Analytics Engine](https://developers.cloudflare.com/analytics/analytics-engine/), allowing to get analytics about anything.

<!-- TODO: config, binding ? -->

Once properly configured, NuxtHub module exposes a server composable to the application.

## `useAnalytics()`
10 changes: 10 additions & 0 deletions docs/content/3.recipes/1.validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: Validation
description:
---

## Blob

### `ensureBlob()`

<!-- TODO -->
10 changes: 10 additions & 0 deletions docs/content/3.recipes/2.hooks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: Hooks
description:
---

## Hooks

### `onHubReady`

<!-- TODO -->
11 changes: 9 additions & 2 deletions src/runtime/server/utils/blob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ export interface BlobListOptions {
cursor?: string
}

export interface BlobPutOptions {
contentType?: string,
contentLength?: string,
addRandomSuffix?: boolean,
[key: string]: any
}

const _r2_buckets: Record<string, R2Bucket> = {}

function _useBucket() {
Expand Down Expand Up @@ -89,7 +96,7 @@ export function useBlob() {

return object.body
},
async put(pathname: string, body: string | ReadableStream<any> | ArrayBuffer | ArrayBufferView | Blob, options: { contentType?: string, contentLength?: string, addRandomSuffix?: boolean, [key: string]: any } = { addRandomSuffix: true }) {
async put(pathname: string, body: string | ReadableStream<any> | ArrayBuffer | ArrayBufferView | Blob, options: BlobPutOptions = { addRandomSuffix: true }) {
pathname = decodeURI(pathname)
const { contentType: optionsContentType, contentLength, addRandomSuffix, ...customMetadata } = options
const contentType = optionsContentType || (body as Blob).type || getContentType(pathname)
Expand Down Expand Up @@ -145,7 +152,7 @@ export function useProxyBlob(projectUrl: string, secretKey?: string) {
method: 'GET'
})
},
async put(pathname: string, body: string | ReadableStream<any> | ArrayBuffer | ArrayBufferView | Blob, options: { contentType?: string, contentLength?: string, addRandomSuffix?: boolean, [key: string]: any } = { addRandomSuffix: true }) {
async put(pathname: string, body: string | ReadableStream<any> | ArrayBuffer | ArrayBufferView | Blob, options: BlobPutOptions = { addRandomSuffix: true }) {
const { contentType, contentLength, ...query } = options
const headers: Record<string, string> = {}
if (contentType) { headers['content-type'] = contentType }
Expand Down

0 comments on commit 1c98fd7

Please sign in to comment.