UNPKG

solobase-js

Version:

A 100% drop-in replacement for the Supabase JavaScript client. Self-hosted Supabase alternative with complete API compatibility.

424 lines 13.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SolobaseStorageClient = exports.SolobaseStorageFileApi = void 0; class SolobaseStorageFileApi { constructor(fetch, bucketId) { this.fetch = fetch; this.bucketId = bucketId; } /** * Upload a file to the bucket */ async upload(path, file, options = {}) { const formData = new FormData(); let fileBlob; if (file instanceof ArrayBuffer) { fileBlob = new Blob([file], { type: options.contentType || 'application/octet-stream' }); } else if (file instanceof Blob) { fileBlob = file; } else { fileBlob = file; } formData.append('file', fileBlob, path.split('/').pop()); if (path.includes('/')) { formData.append('path', path.substring(0, path.lastIndexOf('/'))); } const headers = {}; if (options.cacheControl) { headers['Cache-Control'] = options.cacheControl; } const response = await this.fetch.post(`/storage/v1/object/${this.bucketId}`, { body: formData, headers, }); if (response.error) { return { data: null, error: { message: response.error.message }, }; } return { data: { path }, error: null, }; } /** * Download a file from the bucket */ async download(path) { const response = await this.fetch.get(`/storage/v1/object/${this.bucketId}/${path}`); if (response.error) { return { data: null, error: { message: response.error.message }, }; } return { data: response.data, error: null, }; } /** * List files in the bucket */ async list(path = '', options = {}) { var _a; const query = {}; if (path) { query.path = path; } if (options.limit) { query.limit = options.limit; } if (options.offset) { query.offset = options.offset; } if (options.sortBy) { query.sortBy = `${options.sortBy.column}:${options.sortBy.order}`; } const response = await this.fetch.get(`/storage/v1/object/list/${this.bucketId}`, { query, }); if (response.error) { return { data: null, error: { message: response.error.message }, }; } // Transform the response data to match Supabase format const files = ((_a = response.data) === null || _a === void 0 ? void 0 : _a.data) || response.data || []; return { data: files.map((file) => ({ name: file.name, id: file.id, updated_at: file.updated_at, created_at: file.created_at, last_accessed_at: file.last_accessed_at, metadata: file.metadata, })), error: null, }; } /** * Update/replace a file in the bucket */ async update(path, file, options = {}) { // For update, we use upsert: true return this.upload(path, file, { ...options, upsert: true }); } /** * Move a file within the bucket */ async move(fromPath, toPath) { const response = await this.fetch.post(`/storage/object/move`, { body: { bucketId: this.bucketId, sourceKey: fromPath, destinationKey: toPath, }, }); if (response.error) { return { data: null, error: { message: response.error.message }, }; } return { data: { message: 'Successfully moved' }, error: null, }; } /** * Copy a file within the bucket */ async copy(fromPath, toPath) { const response = await this.fetch.post(`/storage/object/copy`, { body: { bucketId: this.bucketId, sourceKey: fromPath, destinationKey: toPath, }, }); if (response.error) { return { data: null, error: { message: response.error.message }, }; } return { data: { path: toPath }, error: null, }; } /** * Remove files from the bucket */ async remove(paths) { const promises = paths.map(async (path) => { // First get the file info const fileInfo = await this.list(path); if (fileInfo.error || !fileInfo.data) { return null; } const file = fileInfo.data.find(f => f.name === path.split('/').pop()); if (!file) return null; // Delete the file const response = await this.fetch.delete(`/storage/v1/object/${this.bucketId}/${path}`); if (response.error) { throw new Error(response.error.message); } return file; }); try { const results = await Promise.all(promises); const deletedFiles = results.filter(Boolean); return { data: deletedFiles, error: null, }; } catch (error) { return { data: null, error: { message: error instanceof Error ? error.message : 'Delete failed' }, }; } } /** * Create a signed URL for a file */ async createSignedUrl(path, expiresIn = 3600) { const response = await this.fetch.post(`/storage/object/sign/${this.bucketId}/${path}`, { body: { expiresIn }, }); if (response.error) { return { data: null, error: { message: response.error.message }, }; } return { data: { signedUrl: response.data.signedUrl }, error: null, }; } /** * Create signed URLs for multiple files */ async createSignedUrls(paths, expiresIn = 3600) { const promises = paths.map(async (path) => { const result = await this.createSignedUrl(path, expiresIn); if (result.error) { throw new Error(result.error.message); } return { path, signedUrl: result.data.signedUrl, }; }); try { const signedUrls = await Promise.all(promises); return { data: { signedUrls }, error: null, }; } catch (error) { return { data: null, error: { message: error instanceof Error ? error.message : 'Failed to create signed URLs' }, }; } } /** * Get the public URL for a file (if bucket is public) */ getPublicUrl(path) { const publicUrl = `${this.fetch['baseUrl']}/storage/v1/object/public/${this.bucketId}/${path}`; return { data: { publicUrl }, }; } } exports.SolobaseStorageFileApi = SolobaseStorageFileApi; class SolobaseStorageClient { constructor(fetch) { this.fetch = fetch; } /** * Get a reference to a storage bucket */ from(bucketId) { return new SolobaseStorageFileApi(this.fetch, bucketId); } /** * List all buckets */ async listBuckets() { var _a; const response = await this.fetch.get('/dashboard/storage'); if (response.error) { return { data: null, error: { message: response.error.message }, }; } const buckets = ((_a = response.data) === null || _a === void 0 ? void 0 : _a.buckets) || []; return { data: buckets.map((bucket) => { var _a; return ({ id: bucket.id, name: bucket.name, owner: bucket.owner_id, created_at: bucket.created_at, updated_at: bucket.updated_at, public: bucket.public, file_size_limit: bucket.file_size_limit, allowed_mime_types: ((_a = bucket.allowed_mime_types) === null || _a === void 0 ? void 0 : _a.split(',').map((type) => type.trim())) || null, }); }), error: null, }; } /** * Get bucket details */ async getBucket(bucketId) { var _a; const response = await this.fetch.get(`/dashboard/storage/buckets/${bucketId}`); if (response.error) { return { data: null, error: { message: response.error.message }, }; } const bucket = response.data; return { data: { id: bucket.id, name: bucket.name, owner: bucket.owner_id, created_at: bucket.created_at, updated_at: bucket.updated_at, public: bucket.public, file_size_limit: bucket.file_size_limit, allowed_mime_types: ((_a = bucket.allowed_mime_types) === null || _a === void 0 ? void 0 : _a.split(',').map((type) => type.trim())) || null, }, error: null, }; } /** * Create a new bucket */ async createBucket(bucketId, options = {}) { var _a, _b; const response = await this.fetch.post('/dashboard/storage/buckets', { body: { name: bucketId, public: options.public || false, file_size_limit: options.fileSizeLimit, allowed_mime_types: (_a = options.allowedMimeTypes) === null || _a === void 0 ? void 0 : _a.join(','), }, }); if (response.error) { return { data: null, error: { message: response.error.message }, }; } const bucket = response.data; return { data: { id: bucket.id, name: bucket.name, owner: bucket.owner_id, created_at: bucket.created_at, updated_at: bucket.updated_at, public: bucket.public, file_size_limit: bucket.file_size_limit, allowed_mime_types: ((_b = bucket.allowed_mime_types) === null || _b === void 0 ? void 0 : _b.split(',').map((type) => type.trim())) || null, }, error: null, }; } /** * Update bucket configuration */ async updateBucket(bucketId, options) { var _a; const response = await this.fetch.put(`/dashboard/storage/buckets/${bucketId}`, { body: { public: options.public, file_size_limit: options.fileSizeLimit, allowed_mime_types: (_a = options.allowedMimeTypes) === null || _a === void 0 ? void 0 : _a.join(','), }, }); if (response.error) { return { data: null, error: { message: response.error.message }, }; } return { data: { message: 'Successfully updated' }, error: null, }; } /** * Delete a bucket */ async deleteBucket(bucketId) { const response = await this.fetch.delete(`/dashboard/storage/buckets/${bucketId}`, { body: { confirmation: 'DELETE' }, }); if (response.error) { return { data: null, error: { message: response.error.message }, }; } return { data: { message: 'Successfully deleted' }, error: null, }; } /** * Empty a bucket (delete all files) */ async emptyBucket(bucketId) { // First list all files const fileApi = this.from(bucketId); const listResult = await fileApi.list(); if (listResult.error) { return { data: null, error: listResult.error, }; } if (!listResult.data || listResult.data.length === 0) { return { data: { message: 'Bucket is already empty' }, error: null, }; } // Delete all files const filePaths = listResult.data.map(file => file.name); const deleteResult = await fileApi.remove(filePaths); if (deleteResult.error) { return { data: null, error: deleteResult.error, }; } return { data: { message: `Successfully deleted ${filePaths.length} files` }, error: null, }; } } exports.SolobaseStorageClient = SolobaseStorageClient; //# sourceMappingURL=SolobaseStorageClient.js.map