Skip to content

Commit 7dbed14

Browse files
authored
chore: allow any JSON object to be saved in blob store (#901)
The blob store will need to store additional metadata, such as audio duration, in the future. This changes its `metadata` type to any JSON object to allow this. It also adds a test for `blobStore.entry()` to ensure metadata is saved. This change shouldn't affect the external API because the blob store is not directly exposed. It's used internally by `BlobApi`, which did not change.
1 parent 100a973 commit 7dbed14

File tree

4 files changed

+32
-3
lines changed

4 files changed

+32
-3
lines changed

src/blob-store/index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import util from 'node:util'
44
import { discoveryKey } from 'hypercore-crypto'
55
import { TypedEmitter } from 'tiny-typed-emitter'
66
import { LiveDownload } from './live-download.js'
7+
/** @import { JsonObject } from 'type-fest' */
78
/** @import { Readable as NodeReadable } from 'node:stream' */
89
/** @import { Readable as StreamxReadable, Writable } from 'streamx' */
910
/** @import { BlobId } from '../types.js' */
@@ -200,7 +201,7 @@ export class BlobStore {
200201
* @param {Omit<BlobId, 'driveId'>} blobId
201202
* @param {Buffer} blob
202203
* @param {object} [options]
203-
* @param {{mimeType: string}} [options.metadata] Metadata to store with the blob
204+
* @param {JsonObject} [options.metadata] Metadata to store with the blob
204205
* @returns {Promise<string>} discovery key as hex string of hyperdrive where blob is stored
205206
*/
206207
async put({ type, variant, name }, blob, options) {
@@ -212,7 +213,7 @@ export class BlobStore {
212213
/**
213214
* @param {Omit<BlobId, 'driveId'>} blobId
214215
* @param {object} [options]
215-
* @param {{mimeType: string}} [options.metadata] Metadata to store with the blob
216+
* @param {JsonObject} [options.metadata] Metadata to store with the blob
216217
* @returns {Writable & { driveId: string }}
217218
*/
218219
createWriteStream({ type, variant, name }, options) {

src/fastify-plugins/blobs.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ async function routes(fastify, options) {
102102
// Extract the 'mimeType' property of the metadata and use it for the response header if found
103103
if (
104104
metadata &&
105+
typeof metadata === 'object' &&
105106
'mimeType' in metadata &&
106107
typeof metadata.mimeType === 'string'
107108
) {

test/blob-store/blob-store.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,32 @@ test('blobStore.createWriteStream(blobId) and blobStore.createReadStream(blobId)
153153
assert.deepEqual(bndlbuf, diskbuf, 'should be equal')
154154
})
155155

156+
test('blobStore.entry includes metadata if present', async () => {
157+
const { blobStore } = testenv()
158+
159+
const blobId = /** @type {const} */ ({
160+
type: 'photo',
161+
variant: 'original',
162+
name: 'test-file',
163+
})
164+
const ws = blobStore.createWriteStream(blobId, {
165+
metadata: {
166+
foo: 'bar',
167+
baz: [1, 2, 3],
168+
},
169+
})
170+
await pipeline(fs.createReadStream(new URL(import.meta.url)), ws)
171+
172+
const entry = await blobStore.entry({
173+
...blobId,
174+
driveId: ws.driveId,
175+
})
176+
assert.deepEqual(entry?.value.metadata, {
177+
foo: 'bar',
178+
baz: [1, 2, 3],
179+
})
180+
})
181+
156182
test('blobStore.createReadStream should not wait', async () => {
157183
const { blobStore } = testenv()
158184
const expected = await readFile(new URL(import.meta.url))

types/hyperdrive.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ declare module 'hyperdrive' {
44
import Hyperblobs, { BlobId } from 'hyperblobs'
55
import { Readable, Writable } from 'streamx'
66
import { TypedEmitter } from 'tiny-typed-emitter'
7+
import { JsonValue } from 'type-fest'
78

89
interface HyperdriveOptions {
910
onwait: () => void
@@ -39,7 +40,7 @@ declare module 'hyperdrive' {
3940
executable: boolean // whether the blob at path is an executable
4041
linkname: null | string // if entry not symlink, otherwise a string to the entry this links to
4142
blob: BlobId // a Hyperblob id that can be used to fetch the blob associated with this entry
42-
metadata: null | object
43+
metadata: JsonValue
4344
}
4445
}
4546
}

0 commit comments

Comments
 (0)