UNPKG

@monkdb/monkdb

Version:

🚀 Official TypeScript SDK for MonkDB — a unified, AI-native database for diverse data workloads

84 lines • 3.23 kB
// --- src/blobstore/MonkBlobstoreContainer.ts --- import crypto from 'crypto'; import { MonkDigestNotFoundException, MonkBlobLocationNotFoundException, } from '../errors/MonkErrors.js'; import { Readable } from 'stream'; export class MonkBlobstoreContainer { constructor(containerName, connection) { this.containerName = containerName; this.connection = connection; } async computeDigest(stream) { const hash = crypto.createHash('sha1'); for await (const chunk of stream) { hash.update(chunk); } return hash.digest('hex'); } async put(file, digest) { let stream; let buffer; if (file instanceof Blob || file instanceof File) { buffer = Buffer.from(await file.arrayBuffer()); stream = Readable.from(buffer); } else if (Buffer.isBuffer(file)) { buffer = file; stream = Readable.from(buffer); } else if (file instanceof Readable) { // If digest is not provided, we need to buffer the stream to compute it if (!digest) { const chunks = []; for await (const chunk of file) { chunks.push(chunk); } buffer = Buffer.concat(chunks); stream = Readable.from(buffer); } else { stream = file; } } else { throw new Error('Unsupported file type'); } const actualDigest = digest || (await this.computeDigest(Readable.from(buffer))); const headers = { 'Content-Type': 'application/octet-stream' }; const path = `/_blobs/${this.containerName}/${actualDigest}`; const response = await this.connection.client.request('PUT', path, stream, headers); if (!response) throw new Error('Blob upload failed: No response'); return digest ? response.status === 201 : actualDigest; } async get(digest) { const path = `/_blobs/${this.containerName}/${digest}`; const response = await this.connection.client.request('GET', path); if (!response || response.status === 404) { throw new MonkDigestNotFoundException(this.containerName, digest); } if (!response.body) { throw new Error('Blob response missing stream'); } return response.body; } async delete(digest) { const path = `/_blobs/${this.containerName}/${digest}`; const response = await this.connection.client.request('DELETE', path); if (!response) return false; if (response.status === 204) return true; if (response.status === 404) return false; throw new MonkBlobLocationNotFoundException(this.containerName, digest); } async exists(digest) { const path = `/_blobs/${this.containerName}/${digest}`; const response = await this.connection.client.request('HEAD', path); return response?.status === 200; } toString() { return `<BlobContainer '${this.containerName}'>`; } } //# sourceMappingURL=MonkBlobstoreContainer.js.map