@supabase/storage-js 2.80.1-canary.1 → 2.80.1-canary.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +922 -13
- package/dist/main/StorageClient.d.ts +28 -0
- package/dist/main/StorageClient.d.ts.map +1 -1
- package/dist/main/StorageClient.js +38 -5
- package/dist/main/StorageClient.js.map +1 -1
- package/dist/main/index.d.ts +2 -0
- package/dist/main/index.d.ts.map +1 -1
- package/dist/main/index.js +7 -17
- package/dist/main/index.js.map +1 -1
- package/dist/main/lib/constants.d.ts.map +1 -1
- package/dist/main/lib/constants.js +3 -1
- package/dist/main/lib/constants.js.map +1 -1
- package/dist/main/lib/fetch.d.ts.map +1 -1
- package/dist/main/lib/fetch.js +16 -17
- package/dist/main/lib/fetch.js.map +1 -1
- package/dist/main/lib/helpers.d.ts +1 -1
- package/dist/main/lib/helpers.d.ts.map +1 -1
- package/dist/main/lib/helpers.js +4 -57
- package/dist/main/lib/helpers.js.map +1 -1
- package/dist/main/lib/index.d.ts +1 -0
- package/dist/main/lib/index.d.ts.map +1 -1
- package/dist/main/lib/index.js +6 -18
- package/dist/main/lib/index.js.map +1 -1
- package/dist/main/lib/types.d.ts +74 -4
- package/dist/main/lib/types.d.ts.map +1 -1
- package/dist/main/lib/vectors/StorageVectorsClient.d.ts +310 -0
- package/dist/main/lib/vectors/StorageVectorsClient.d.ts.map +1 -0
- package/dist/main/lib/vectors/StorageVectorsClient.js +366 -0
- package/dist/main/lib/vectors/StorageVectorsClient.js.map +1 -0
- package/dist/main/lib/vectors/VectorBucketApi.d.ts +129 -0
- package/dist/main/lib/vectors/VectorBucketApi.d.ts.map +1 -0
- package/dist/main/lib/vectors/VectorBucketApi.js +199 -0
- package/dist/main/lib/vectors/VectorBucketApi.js.map +1 -0
- package/dist/main/lib/vectors/VectorDataApi.d.ts +221 -0
- package/dist/main/lib/vectors/VectorDataApi.d.ts.map +1 -0
- package/dist/main/lib/vectors/VectorDataApi.js +336 -0
- package/dist/main/lib/vectors/VectorDataApi.js.map +1 -0
- package/dist/main/lib/vectors/VectorIndexApi.d.ts +157 -0
- package/dist/main/lib/vectors/VectorIndexApi.d.ts.map +1 -0
- package/dist/main/lib/vectors/VectorIndexApi.js +218 -0
- package/dist/main/lib/vectors/VectorIndexApi.js.map +1 -0
- package/dist/main/lib/vectors/constants.d.ts +5 -0
- package/dist/main/lib/vectors/constants.d.ts.map +1 -0
- package/dist/main/lib/vectors/constants.js +9 -0
- package/dist/main/lib/vectors/constants.js.map +1 -0
- package/dist/main/lib/vectors/errors.d.ts +55 -0
- package/dist/main/lib/vectors/errors.d.ts.map +1 -0
- package/dist/main/lib/vectors/errors.js +76 -0
- package/dist/main/lib/vectors/errors.js.map +1 -0
- package/dist/main/lib/vectors/fetch.d.ts +57 -0
- package/dist/main/lib/vectors/fetch.d.ts.map +1 -0
- package/dist/main/lib/vectors/fetch.js +167 -0
- package/dist/main/lib/vectors/fetch.js.map +1 -0
- package/dist/main/lib/vectors/helpers.d.ts +46 -0
- package/dist/main/lib/vectors/helpers.d.ts.map +1 -0
- package/dist/main/lib/vectors/helpers.js +74 -0
- package/dist/main/lib/vectors/helpers.js.map +1 -0
- package/dist/main/lib/vectors/index.d.ts +11 -0
- package/dist/main/lib/vectors/index.d.ts.map +1 -0
- package/dist/main/lib/vectors/index.js +31 -0
- package/dist/main/lib/vectors/index.js.map +1 -0
- package/dist/main/lib/vectors/types.d.ts +277 -0
- package/dist/main/lib/vectors/types.d.ts.map +1 -0
- package/dist/main/lib/vectors/types.js +3 -0
- package/dist/main/lib/vectors/types.js.map +1 -0
- package/dist/main/lib/version.d.ts +1 -1
- package/dist/main/lib/version.js +1 -1
- package/dist/main/packages/BlobDownloadBuilder.d.ts +6 -1
- package/dist/main/packages/BlobDownloadBuilder.d.ts.map +1 -1
- package/dist/main/packages/BlobDownloadBuilder.js +20 -15
- package/dist/main/packages/BlobDownloadBuilder.js.map +1 -1
- package/dist/main/packages/StorageAnalyticsApi.d.ts +123 -0
- package/dist/main/packages/StorageAnalyticsApi.d.ts.map +1 -0
- package/dist/main/packages/StorageAnalyticsApi.js +164 -0
- package/dist/main/packages/StorageAnalyticsApi.js.map +1 -0
- package/dist/main/packages/StorageBucketApi.d.ts +3 -2
- package/dist/main/packages/StorageBucketApi.d.ts.map +1 -1
- package/dist/main/packages/StorageBucketApi.js +34 -18
- package/dist/main/packages/StorageBucketApi.js.map +1 -1
- package/dist/main/packages/StorageFileApi.d.ts.map +1 -1
- package/dist/main/packages/StorageFileApi.js +28 -29
- package/dist/main/packages/StorageFileApi.js.map +1 -1
- package/dist/main/packages/StreamDownloadBuilder.js +2 -10
- package/dist/main/packages/StreamDownloadBuilder.js.map +1 -1
- package/dist/module/StorageClient.d.ts +28 -0
- package/dist/module/StorageClient.d.ts.map +1 -1
- package/dist/module/StorageClient.js +35 -0
- package/dist/module/StorageClient.js.map +1 -1
- package/dist/module/index.d.ts +2 -0
- package/dist/module/index.d.ts.map +1 -1
- package/dist/module/index.js +2 -0
- package/dist/module/index.js.map +1 -1
- package/dist/module/lib/constants.d.ts.map +1 -1
- package/dist/module/lib/constants.js +3 -1
- package/dist/module/lib/constants.js.map +1 -1
- package/dist/module/lib/fetch.d.ts.map +1 -1
- package/dist/module/lib/fetch.js +9 -10
- package/dist/module/lib/fetch.js.map +1 -1
- package/dist/module/lib/helpers.d.ts +1 -1
- package/dist/module/lib/helpers.d.ts.map +1 -1
- package/dist/module/lib/helpers.js +4 -24
- package/dist/module/lib/helpers.js.map +1 -1
- package/dist/module/lib/index.d.ts +1 -0
- package/dist/module/lib/index.d.ts.map +1 -1
- package/dist/module/lib/index.js +1 -0
- package/dist/module/lib/index.js.map +1 -1
- package/dist/module/lib/types.d.ts +74 -4
- package/dist/module/lib/types.d.ts.map +1 -1
- package/dist/module/lib/vectors/StorageVectorsClient.d.ts +310 -0
- package/dist/module/lib/vectors/StorageVectorsClient.d.ts.map +1 -0
- package/dist/module/lib/vectors/StorageVectorsClient.js +360 -0
- package/dist/module/lib/vectors/StorageVectorsClient.js.map +1 -0
- package/dist/module/lib/vectors/VectorBucketApi.d.ts +129 -0
- package/dist/module/lib/vectors/VectorBucketApi.d.ts.map +1 -0
- package/dist/module/lib/vectors/VectorBucketApi.js +196 -0
- package/dist/module/lib/vectors/VectorBucketApi.js.map +1 -0
- package/dist/module/lib/vectors/VectorDataApi.d.ts +221 -0
- package/dist/module/lib/vectors/VectorDataApi.d.ts.map +1 -0
- package/dist/module/lib/vectors/VectorDataApi.js +333 -0
- package/dist/module/lib/vectors/VectorDataApi.js.map +1 -0
- package/dist/module/lib/vectors/VectorIndexApi.d.ts +157 -0
- package/dist/module/lib/vectors/VectorIndexApi.d.ts.map +1 -0
- package/dist/module/lib/vectors/VectorIndexApi.js +215 -0
- package/dist/module/lib/vectors/VectorIndexApi.js.map +1 -0
- package/dist/module/lib/vectors/constants.d.ts +5 -0
- package/dist/module/lib/vectors/constants.d.ts.map +1 -0
- package/dist/module/lib/vectors/constants.js +6 -0
- package/dist/module/lib/vectors/constants.js.map +1 -0
- package/dist/module/lib/vectors/errors.d.ts +55 -0
- package/dist/module/lib/vectors/errors.d.ts.map +1 -0
- package/dist/module/lib/vectors/errors.js +69 -0
- package/dist/module/lib/vectors/errors.js.map +1 -0
- package/dist/module/lib/vectors/fetch.d.ts +57 -0
- package/dist/module/lib/vectors/fetch.d.ts.map +1 -0
- package/dist/module/lib/vectors/fetch.js +161 -0
- package/dist/module/lib/vectors/fetch.js.map +1 -0
- package/dist/module/lib/vectors/helpers.d.ts +46 -0
- package/dist/module/lib/vectors/helpers.d.ts.map +1 -0
- package/dist/module/lib/vectors/helpers.js +66 -0
- package/dist/module/lib/vectors/helpers.js.map +1 -0
- package/dist/module/lib/vectors/index.d.ts +11 -0
- package/dist/module/lib/vectors/index.d.ts.map +1 -0
- package/dist/module/lib/vectors/index.js +11 -0
- package/dist/module/lib/vectors/index.js.map +1 -0
- package/dist/module/lib/vectors/types.d.ts +277 -0
- package/dist/module/lib/vectors/types.d.ts.map +1 -0
- package/dist/module/lib/vectors/types.js +2 -0
- package/dist/module/lib/vectors/types.js.map +1 -0
- package/dist/module/lib/version.d.ts +1 -1
- package/dist/module/lib/version.js +1 -1
- package/dist/module/packages/BlobDownloadBuilder.d.ts +6 -1
- package/dist/module/packages/BlobDownloadBuilder.d.ts.map +1 -1
- package/dist/module/packages/BlobDownloadBuilder.js +20 -11
- package/dist/module/packages/BlobDownloadBuilder.js.map +1 -1
- package/dist/module/packages/StorageAnalyticsApi.d.ts +123 -0
- package/dist/module/packages/StorageAnalyticsApi.d.ts.map +1 -0
- package/dist/module/packages/StorageAnalyticsApi.js +161 -0
- package/dist/module/packages/StorageAnalyticsApi.js.map +1 -0
- package/dist/module/packages/StorageBucketApi.d.ts +3 -2
- package/dist/module/packages/StorageBucketApi.d.ts.map +1 -1
- package/dist/module/packages/StorageBucketApi.js +28 -12
- package/dist/module/packages/StorageBucketApi.js.map +1 -1
- package/dist/module/packages/StorageFileApi.d.ts.map +1 -1
- package/dist/module/packages/StorageFileApi.js +13 -11
- package/dist/module/packages/StorageFileApi.js.map +1 -1
- package/dist/module/packages/StreamDownloadBuilder.js +1 -9
- package/dist/module/packages/StreamDownloadBuilder.js.map +1 -1
- package/dist/tsconfig.module.tsbuildinfo +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/umd/supabase.js +1 -1
- package/package.json +9 -16
- package/src/StorageClient.ts +37 -0
- package/src/index.ts +2 -0
- package/src/lib/constants.ts +3 -1
- package/src/lib/fetch.ts +5 -1
- package/src/lib/helpers.ts +3 -14
- package/src/lib/index.ts +1 -0
- package/src/lib/types.ts +83 -2
- package/src/lib/vectors/StorageVectorsClient.ts +405 -0
- package/src/lib/vectors/VectorBucketApi.ts +217 -0
- package/src/lib/vectors/VectorDataApi.ts +341 -0
- package/src/lib/vectors/VectorIndexApi.ts +245 -0
- package/src/lib/vectors/constants.ts +5 -0
- package/src/lib/vectors/errors.ts +78 -0
- package/src/lib/vectors/fetch.ts +218 -0
- package/src/lib/vectors/helpers.ts +79 -0
- package/src/lib/vectors/index.ts +66 -0
- package/src/lib/vectors/types.ts +299 -0
- package/src/lib/version.ts +1 -1
- package/src/packages/BlobDownloadBuilder.ts +22 -2
- package/src/packages/StorageAnalyticsApi.ts +199 -0
- package/src/packages/StorageBucketApi.ts +29 -4
- package/src/packages/StorageFileApi.ts +15 -2
package/README.md
CHANGED
|
@@ -1,14 +1,52 @@
|
|
|
1
|
-
|
|
1
|
+
<br />
|
|
2
|
+
<p align="center">
|
|
3
|
+
<a href="https://supabase.io">
|
|
4
|
+
<picture>
|
|
5
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--dark.svg">
|
|
6
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/supabase-logo-wordmark--light.svg">
|
|
7
|
+
<img alt="Supabase Logo" width="300" src="https://raw.githubusercontent.com/supabase/supabase/master/packages/common/assets/images/logo-preview.jpg">
|
|
8
|
+
</picture>
|
|
9
|
+
</a>
|
|
10
|
+
|
|
11
|
+
<h1 align="center">Supabase Storage JS SDK</h1>
|
|
12
|
+
|
|
13
|
+
<h3 align="center">JavaScript SDK to interact with Supabase Storage, including file storage and vector embeddings.</h3>
|
|
14
|
+
|
|
15
|
+
<p align="center">
|
|
16
|
+
<a href="https://supabase.com/docs/guides/storage">Guides</a>
|
|
17
|
+
·
|
|
18
|
+
<a href="https://supabase.com/docs/reference/javascript/storage-createbucket">Reference Docs</a>
|
|
19
|
+
·
|
|
20
|
+
<a href="https://supabase.github.io/supabase-js/storage-js/v2/spec.json">TypeDoc</a>
|
|
21
|
+
</p>
|
|
22
|
+
</p>
|
|
2
23
|
|
|
3
24
|
<div align="center">
|
|
4
25
|
|
|
26
|
+
[](https://github.com/supabase/supabase-js/actions?query=branch%3Amaster)
|
|
27
|
+
[](https://www.npmjs.com/package/@supabase/storage-js)
|
|
28
|
+
[](#license)
|
|
5
29
|
[](https://pkg.pr.new/~/supabase/storage-js)
|
|
6
30
|
|
|
7
31
|
</div>
|
|
8
32
|
|
|
9
|
-
|
|
33
|
+
## Requirements
|
|
10
34
|
|
|
11
|
-
-
|
|
35
|
+
- **Node.js 20 or later** (Node.js 18 support dropped as of October 31, 2025)
|
|
36
|
+
- For browser support, all modern browsers are supported
|
|
37
|
+
|
|
38
|
+
> ⚠️ **Node.js 18 Deprecation Notice**
|
|
39
|
+
>
|
|
40
|
+
> Node.js 18 reached end-of-life on April 30, 2025. As announced in [our deprecation notice](https://github.com/orgs/supabase/discussions/37217), support for Node.js 18 was dropped on October 31, 2025.
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
- **File Storage**: Upload, download, list, move, and delete files
|
|
45
|
+
- **Access Control**: Public and private buckets with fine-grained permissions
|
|
46
|
+
- **Signed URLs**: Generate time-limited URLs for secure file access
|
|
47
|
+
- **Image Transformations**: On-the-fly image resizing and optimization
|
|
48
|
+
- **Vector Embeddings**: Store and query high-dimensional embeddings with similarity search
|
|
49
|
+
- **Analytics Buckets**: Iceberg table-based buckets optimized for analytical queries and data processing
|
|
12
50
|
|
|
13
51
|
## Quick Start Guide
|
|
14
52
|
|
|
@@ -20,6 +58,30 @@ npm install @supabase/storage-js
|
|
|
20
58
|
|
|
21
59
|
### Connecting to the storage backend
|
|
22
60
|
|
|
61
|
+
There are two ways to use the Storage SDK:
|
|
62
|
+
|
|
63
|
+
#### Option 1: Via Supabase Client (Recommended)
|
|
64
|
+
|
|
65
|
+
If you're already using `@supabase/supabase-js`, access storage through the client:
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
import { createClient } from '@supabase/supabase-js'
|
|
69
|
+
|
|
70
|
+
const supabase = createClient('https://<project_ref>.supabase.co', '<your-anon-key>')
|
|
71
|
+
|
|
72
|
+
// Access storage
|
|
73
|
+
const storage = supabase.storage
|
|
74
|
+
|
|
75
|
+
// Access different bucket types
|
|
76
|
+
const regularBucket = storage.from('my-bucket')
|
|
77
|
+
const vectorBucket = storage.vectors.from('embeddings-bucket')
|
|
78
|
+
const analyticsBucket = storage.analytics // Analytics API
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
#### Option 2: Standalone StorageClient
|
|
82
|
+
|
|
83
|
+
For applications that only need storage functionality:
|
|
84
|
+
|
|
23
85
|
```js
|
|
24
86
|
import { StorageClient } from '@supabase/storage-js'
|
|
25
87
|
|
|
@@ -30,8 +92,80 @@ const storageClient = new StorageClient(STORAGE_URL, {
|
|
|
30
92
|
apikey: SERVICE_KEY,
|
|
31
93
|
Authorization: `Bearer ${SERVICE_KEY}`,
|
|
32
94
|
})
|
|
95
|
+
|
|
96
|
+
// Access different bucket types
|
|
97
|
+
const regularBucket = storageClient.from('my-bucket')
|
|
98
|
+
const vectorBucket = storageClient.vectors.from('embeddings-bucket')
|
|
99
|
+
const analyticsBucket = storageClient.analytics // Analytics API
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
> **When to use each approach:**
|
|
103
|
+
>
|
|
104
|
+
> - Use `supabase.storage` when working with other Supabase features (auth, database, etc.)
|
|
105
|
+
> - Use `new StorageClient()` for storage-only applications or when you need fine-grained control
|
|
106
|
+
|
|
107
|
+
### Understanding Bucket Types
|
|
108
|
+
|
|
109
|
+
Supabase Storage supports three types of buckets, each optimized for different use cases:
|
|
110
|
+
|
|
111
|
+
#### 1. Regular Storage Buckets (File Storage)
|
|
112
|
+
|
|
113
|
+
Standard buckets for storing files, images, videos, and other assets.
|
|
114
|
+
|
|
115
|
+
```js
|
|
116
|
+
// Create regular storage bucket
|
|
117
|
+
const { data, error } = await storageClient.createBucket('my-files', {
|
|
118
|
+
public: false,
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
// Upload files
|
|
122
|
+
await storageClient.from('my-files').upload('avatar.png', file)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Use cases:** User uploads, media assets, documents, backups
|
|
126
|
+
|
|
127
|
+
#### 2. Vector Buckets (Embeddings Storage)
|
|
128
|
+
|
|
129
|
+
Specialized buckets for storing and querying high-dimensional vector embeddings.
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
// Create vector bucket
|
|
133
|
+
await storageClient.vectors.createBucket('embeddings-prod')
|
|
134
|
+
|
|
135
|
+
// Create index and insert vectors
|
|
136
|
+
const bucket = storageClient.vectors.from('embeddings-prod')
|
|
137
|
+
await bucket.createIndex({
|
|
138
|
+
indexName: 'documents',
|
|
139
|
+
dimension: 1536,
|
|
140
|
+
distanceMetric: 'cosine',
|
|
141
|
+
})
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Use cases:** Semantic search, AI-powered recommendations, similarity matching
|
|
145
|
+
|
|
146
|
+
**[See full Vector Embeddings documentation below](#vector-embeddings)**
|
|
147
|
+
|
|
148
|
+
#### 3. Analytics Buckets
|
|
149
|
+
|
|
150
|
+
Specialized buckets using Apache Iceberg table format, optimized for analytical queries and large-scale data processing.
|
|
151
|
+
|
|
152
|
+
```js
|
|
153
|
+
// Create analytics bucket
|
|
154
|
+
await storageClient.analytics.createBucket('analytics-data')
|
|
155
|
+
|
|
156
|
+
// List analytics buckets
|
|
157
|
+
const { data, error } = await storageClient.analytics.listBuckets()
|
|
158
|
+
|
|
159
|
+
// Delete analytics bucket
|
|
160
|
+
await storageClient.analytics.deleteBucket('analytics-data')
|
|
33
161
|
```
|
|
34
162
|
|
|
163
|
+
**Use cases:** Time-series data, analytical queries, data lakes, large-scale data processing, business intelligence
|
|
164
|
+
|
|
165
|
+
**[See full Analytics Buckets documentation below](#analytics-buckets)**
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
35
169
|
### Handling resources
|
|
36
170
|
|
|
37
171
|
#### Handling Storage Buckets
|
|
@@ -156,9 +290,791 @@ const storageClient = new StorageClient(STORAGE_URL, {
|
|
|
156
290
|
const { data, error } = await storageClient.from('public-bucket').getPublicUrl('path/to/file')
|
|
157
291
|
```
|
|
158
292
|
|
|
293
|
+
## Analytics Buckets
|
|
294
|
+
|
|
295
|
+
Supabase Storage provides specialized analytics buckets using Apache Iceberg table format, optimized for analytical workloads and large-scale data processing. These buckets are designed for data lake architectures, time-series data, and business intelligence applications.
|
|
296
|
+
|
|
297
|
+
### What are Analytics Buckets?
|
|
298
|
+
|
|
299
|
+
Analytics buckets use the Apache Iceberg open table format, providing:
|
|
300
|
+
|
|
301
|
+
- **ACID transactions** for data consistency
|
|
302
|
+
- **Schema evolution** without data rewrites
|
|
303
|
+
- **Time travel** to query historical data
|
|
304
|
+
- **Efficient metadata management** for large datasets
|
|
305
|
+
- **Optimized for analytical queries** rather than individual file operations
|
|
306
|
+
|
|
307
|
+
### When to Use Analytics Buckets
|
|
308
|
+
|
|
309
|
+
**Use analytics buckets for:**
|
|
310
|
+
|
|
311
|
+
- Time-series data (logs, metrics, events)
|
|
312
|
+
- Data lake architectures
|
|
313
|
+
- Business intelligence and reporting
|
|
314
|
+
- Large-scale batch processing
|
|
315
|
+
- Analytical workloads requiring ACID guarantees
|
|
316
|
+
|
|
317
|
+
**Use regular storage buckets for:**
|
|
318
|
+
|
|
319
|
+
- User file uploads (images, documents, videos)
|
|
320
|
+
- Individual file management
|
|
321
|
+
- Content delivery
|
|
322
|
+
- Simple object storage needs
|
|
323
|
+
|
|
324
|
+
### Quick Start
|
|
325
|
+
|
|
326
|
+
You can access analytics functionality through the `analytics` property on your storage client:
|
|
327
|
+
|
|
328
|
+
#### Via Supabase Client
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
import { createClient } from '@supabase/supabase-js'
|
|
332
|
+
|
|
333
|
+
const supabase = createClient('https://your-project.supabase.co', 'your-anon-key')
|
|
334
|
+
|
|
335
|
+
// Access analytics operations
|
|
336
|
+
const analytics = supabase.storage.analytics
|
|
337
|
+
|
|
338
|
+
// Create an analytics bucket
|
|
339
|
+
const { data, error } = await analytics.createBucket('analytics-data')
|
|
340
|
+
if (error) {
|
|
341
|
+
console.error('Failed to create analytics bucket:', error.message)
|
|
342
|
+
} else {
|
|
343
|
+
console.log('Created bucket:', data.name)
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
#### Via StorageClient
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
import { StorageClient } from '@supabase/storage-js'
|
|
351
|
+
|
|
352
|
+
const storageClient = new StorageClient('https://your-project.supabase.co/storage/v1', {
|
|
353
|
+
apikey: 'YOUR_API_KEY',
|
|
354
|
+
Authorization: 'Bearer YOUR_TOKEN',
|
|
355
|
+
})
|
|
356
|
+
|
|
357
|
+
// Access analytics operations
|
|
358
|
+
const analytics = storageClient.analytics
|
|
359
|
+
|
|
360
|
+
// Create an analytics bucket
|
|
361
|
+
await analytics.createBucket('analytics-data')
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### API Reference
|
|
365
|
+
|
|
366
|
+
#### Create Analytics Bucket
|
|
367
|
+
|
|
368
|
+
Creates a new analytics bucket using Iceberg table format:
|
|
369
|
+
|
|
370
|
+
```typescript
|
|
371
|
+
const { data, error } = await analytics.createBucket('my-analytics-bucket')
|
|
372
|
+
|
|
373
|
+
if (error) {
|
|
374
|
+
console.error('Error:', error.message)
|
|
375
|
+
} else {
|
|
376
|
+
console.log('Created bucket:', data)
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
**Returns:**
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
{
|
|
384
|
+
data: {
|
|
385
|
+
id: string
|
|
386
|
+
type: 'ANALYTICS'
|
|
387
|
+
format: string
|
|
388
|
+
created_at: string
|
|
389
|
+
updated_at: string
|
|
390
|
+
} | null
|
|
391
|
+
error: StorageError | null
|
|
392
|
+
}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
#### List Analytics Buckets
|
|
396
|
+
|
|
397
|
+
Retrieves all analytics buckets in your project with optional filtering and pagination:
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
const { data, error } = await analytics.listBuckets({
|
|
401
|
+
limit: 10,
|
|
402
|
+
offset: 0,
|
|
403
|
+
sortColumn: 'created_at',
|
|
404
|
+
sortOrder: 'desc',
|
|
405
|
+
search: 'prod',
|
|
406
|
+
})
|
|
407
|
+
|
|
408
|
+
if (data) {
|
|
409
|
+
console.log(`Found ${data.length} analytics buckets`)
|
|
410
|
+
data.forEach((bucket) => {
|
|
411
|
+
console.log(`- ${bucket.id} (created: ${bucket.created_at})`)
|
|
412
|
+
})
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
**Parameters:**
|
|
417
|
+
|
|
418
|
+
- `limit?: number` - Maximum number of buckets to return
|
|
419
|
+
- `offset?: number` - Number of buckets to skip (for pagination)
|
|
420
|
+
- `sortColumn?: 'id' | 'name' | 'created_at' | 'updated_at'` - Column to sort by
|
|
421
|
+
- `sortOrder?: 'asc' | 'desc'` - Sort direction
|
|
422
|
+
- `search?: string` - Search term to filter bucket names
|
|
423
|
+
|
|
424
|
+
**Returns:**
|
|
425
|
+
|
|
426
|
+
```typescript
|
|
427
|
+
{
|
|
428
|
+
data: AnalyticBucket[] | null
|
|
429
|
+
error: StorageError | null
|
|
430
|
+
}
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
**Example with Pagination:**
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
// Fetch first page
|
|
437
|
+
const firstPage = await analytics.listBuckets({
|
|
438
|
+
limit: 100,
|
|
439
|
+
offset: 0,
|
|
440
|
+
sortColumn: 'created_at',
|
|
441
|
+
sortOrder: 'desc',
|
|
442
|
+
})
|
|
443
|
+
|
|
444
|
+
// Fetch second page
|
|
445
|
+
const secondPage = await analytics.listBuckets({
|
|
446
|
+
limit: 100,
|
|
447
|
+
offset: 100,
|
|
448
|
+
sortColumn: 'created_at',
|
|
449
|
+
sortOrder: 'desc',
|
|
450
|
+
})
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
#### Delete Analytics Bucket
|
|
454
|
+
|
|
455
|
+
Deletes an analytics bucket. The bucket must be empty before deletion.
|
|
456
|
+
|
|
457
|
+
```typescript
|
|
458
|
+
const { data, error } = await analytics.deleteBucket('old-analytics-bucket')
|
|
459
|
+
|
|
460
|
+
if (error) {
|
|
461
|
+
console.error('Failed to delete:', error.message)
|
|
462
|
+
} else {
|
|
463
|
+
console.log('Bucket deleted:', data.message)
|
|
464
|
+
}
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
**Returns:**
|
|
468
|
+
|
|
469
|
+
```typescript
|
|
470
|
+
{
|
|
471
|
+
data: { message: string } | null
|
|
472
|
+
error: StorageError | null
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
> **Note:** A bucket cannot be deleted if it contains data. You must empty the bucket first.
|
|
477
|
+
|
|
478
|
+
### Error Handling
|
|
479
|
+
|
|
480
|
+
Analytics buckets use the same error handling pattern as the rest of the Storage SDK:
|
|
481
|
+
|
|
482
|
+
```typescript
|
|
483
|
+
const { data, error } = await analytics.createBucket('my-bucket')
|
|
484
|
+
|
|
485
|
+
if (error) {
|
|
486
|
+
console.error('Error:', error.message)
|
|
487
|
+
console.error('Status:', error.status)
|
|
488
|
+
console.error('Status Code:', error.statusCode)
|
|
489
|
+
// Handle error appropriately
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
#### Throwing Errors
|
|
494
|
+
|
|
495
|
+
You can configure the client to throw errors instead of returning them:
|
|
496
|
+
|
|
497
|
+
```typescript
|
|
498
|
+
const analytics = storageClient.analytics
|
|
499
|
+
analytics.throwOnError()
|
|
500
|
+
|
|
501
|
+
try {
|
|
502
|
+
const { data } = await analytics.createBucket('my-bucket')
|
|
503
|
+
// data is guaranteed to be present
|
|
504
|
+
console.log('Success:', data)
|
|
505
|
+
} catch (error) {
|
|
506
|
+
if (error instanceof StorageApiError) {
|
|
507
|
+
console.error('API Error:', error.statusCode, error.message)
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
### TypeScript Types
|
|
513
|
+
|
|
514
|
+
The library exports TypeScript types for analytics buckets:
|
|
515
|
+
|
|
516
|
+
```typescript
|
|
517
|
+
import type { AnalyticBucket, BucketType, StorageError } from '@supabase/storage-js'
|
|
518
|
+
|
|
519
|
+
// AnalyticBucket type
|
|
520
|
+
interface AnalyticBucket {
|
|
521
|
+
id: string
|
|
522
|
+
type: 'ANALYTICS'
|
|
523
|
+
format: string
|
|
524
|
+
created_at: string
|
|
525
|
+
updated_at: string
|
|
526
|
+
}
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
### Common Patterns
|
|
530
|
+
|
|
531
|
+
#### Checking if a Bucket Exists
|
|
532
|
+
|
|
533
|
+
```typescript
|
|
534
|
+
async function bucketExists(bucketName: string): Promise<boolean> {
|
|
535
|
+
const { data, error } = await analytics.listBuckets({
|
|
536
|
+
search: bucketName,
|
|
537
|
+
})
|
|
538
|
+
|
|
539
|
+
if (error) {
|
|
540
|
+
console.error('Error checking bucket:', error.message)
|
|
541
|
+
return false
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
return data?.some((bucket) => bucket.id === bucketName) ?? false
|
|
545
|
+
}
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
#### Creating Bucket with Error Handling
|
|
549
|
+
|
|
550
|
+
```typescript
|
|
551
|
+
async function ensureAnalyticsBucket(bucketName: string) {
|
|
552
|
+
// Try to create the bucket
|
|
553
|
+
const { data, error } = await analytics.createBucket(bucketName)
|
|
554
|
+
|
|
555
|
+
if (error) {
|
|
556
|
+
// Check if bucket already exists (conflict error)
|
|
557
|
+
if (error.statusCode === '409') {
|
|
558
|
+
console.log(`Bucket '${bucketName}' already exists`)
|
|
559
|
+
return { success: true, created: false }
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// Other error occurred
|
|
563
|
+
console.error('Failed to create bucket:', error.message)
|
|
564
|
+
return { success: false, error }
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
console.log(`Created new bucket: '${bucketName}'`)
|
|
568
|
+
return { success: true, created: true, data }
|
|
569
|
+
}
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
#### Listing All Buckets with Pagination
|
|
573
|
+
|
|
574
|
+
```typescript
|
|
575
|
+
async function getAllAnalyticsBuckets() {
|
|
576
|
+
const allBuckets: AnalyticBucket[] = []
|
|
577
|
+
let offset = 0
|
|
578
|
+
const limit = 100
|
|
579
|
+
|
|
580
|
+
while (true) {
|
|
581
|
+
const { data, error } = await analytics.listBuckets({
|
|
582
|
+
limit,
|
|
583
|
+
offset,
|
|
584
|
+
sortColumn: 'created_at',
|
|
585
|
+
sortOrder: 'desc',
|
|
586
|
+
})
|
|
587
|
+
|
|
588
|
+
if (error) {
|
|
589
|
+
console.error('Error fetching buckets:', error.message)
|
|
590
|
+
break
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
if (!data || data.length === 0) {
|
|
594
|
+
break
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
allBuckets.push(...data)
|
|
598
|
+
|
|
599
|
+
// If we got fewer results than the limit, we've reached the end
|
|
600
|
+
if (data.length < limit) {
|
|
601
|
+
break
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
offset += limit
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
return allBuckets
|
|
608
|
+
}
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
## Vector Embeddings
|
|
612
|
+
|
|
613
|
+
Supabase Storage provides built-in support for storing and querying high-dimensional vector embeddings, powered by S3 Vectors. This enables semantic search, similarity matching, and AI-powered applications without needing a separate vector database.
|
|
614
|
+
|
|
615
|
+
> **Note:** Vector embeddings functionality is available in `@supabase/storage-js` v2.76 and later.
|
|
616
|
+
|
|
617
|
+
### Features
|
|
618
|
+
|
|
619
|
+
- **Vector Buckets**: Organize vector indexes into logical containers
|
|
620
|
+
- **Vector Indexes**: Define schemas with configurable dimensions and distance metrics
|
|
621
|
+
- **Batch Operations**: Insert/update/delete up to 500 vectors per request
|
|
622
|
+
- **Similarity Search**: Query for nearest neighbors using cosine, euclidean, or dot product distance
|
|
623
|
+
- **Metadata Filtering**: Store and filter vectors by arbitrary JSON metadata
|
|
624
|
+
- **Pagination**: Efficiently scan large vector datasets
|
|
625
|
+
- **Parallel Scanning**: Distribute scans across multiple workers for high throughput
|
|
626
|
+
- **Cross-platform**: Works in Node.js, browsers, and edge runtimes
|
|
627
|
+
|
|
628
|
+
### Quick Start
|
|
629
|
+
|
|
630
|
+
You can access vector functionality in three ways, depending on your use case:
|
|
631
|
+
|
|
632
|
+
#### Option 1: Via Supabase Client (Most Common)
|
|
633
|
+
|
|
634
|
+
If you're using the full Supabase client:
|
|
635
|
+
|
|
636
|
+
```typescript
|
|
637
|
+
import { createClient } from '@supabase/supabase-js'
|
|
638
|
+
|
|
639
|
+
const supabase = createClient('https://your-project.supabase.co', 'your-anon-key')
|
|
640
|
+
|
|
641
|
+
// Access vector operations through storage
|
|
642
|
+
const vectors = supabase.storage.vectors
|
|
643
|
+
|
|
644
|
+
// Create a vector bucket
|
|
645
|
+
await vectors.createBucket('embeddings-prod')
|
|
646
|
+
|
|
647
|
+
// Create an index
|
|
648
|
+
const bucket = vectors.from('embeddings-prod')
|
|
649
|
+
await bucket.createIndex({
|
|
650
|
+
indexName: 'documents-openai',
|
|
651
|
+
dataType: 'float32',
|
|
652
|
+
dimension: 1536,
|
|
653
|
+
distanceMetric: 'cosine',
|
|
654
|
+
})
|
|
655
|
+
|
|
656
|
+
// Insert vectors
|
|
657
|
+
const index = bucket.index('documents-openai')
|
|
658
|
+
await index.putVectors({
|
|
659
|
+
vectors: [
|
|
660
|
+
{
|
|
661
|
+
key: 'doc-1',
|
|
662
|
+
data: { float32: [0.1, 0.2, 0.3 /* ...1536 dimensions */] },
|
|
663
|
+
metadata: { title: 'Introduction', category: 'docs' },
|
|
664
|
+
},
|
|
665
|
+
],
|
|
666
|
+
})
|
|
667
|
+
|
|
668
|
+
// Query similar vectors
|
|
669
|
+
const { data, error } = await index.queryVectors({
|
|
670
|
+
queryVector: { float32: [0.15, 0.25, 0.35 /* ...1536 dimensions */] },
|
|
671
|
+
topK: 5,
|
|
672
|
+
returnDistance: true,
|
|
673
|
+
returnMetadata: true,
|
|
674
|
+
})
|
|
675
|
+
|
|
676
|
+
if (data) {
|
|
677
|
+
data.matches.forEach((match) => {
|
|
678
|
+
console.log(`${match.key}: distance=${match.distance}`)
|
|
679
|
+
console.log('Metadata:', match.metadata)
|
|
680
|
+
})
|
|
681
|
+
}
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
#### Option 2: Via StorageClient
|
|
685
|
+
|
|
686
|
+
If you're using the standalone `StorageClient` for storage operations, access vectors through the `vectors` property:
|
|
687
|
+
|
|
688
|
+
```typescript
|
|
689
|
+
import { StorageClient } from '@supabase/storage-js'
|
|
690
|
+
|
|
691
|
+
const storageClient = new StorageClient('https://your-project.supabase.co/storage/v1', {
|
|
692
|
+
apikey: 'YOUR_API_KEY',
|
|
693
|
+
Authorization: 'Bearer YOUR_TOKEN',
|
|
694
|
+
})
|
|
695
|
+
|
|
696
|
+
// Access vector operations
|
|
697
|
+
const vectors = storageClient.vectors
|
|
698
|
+
|
|
699
|
+
// Use the same API as shown in Option 1
|
|
700
|
+
await vectors.createBucket('embeddings-prod')
|
|
701
|
+
const bucket = vectors.from('embeddings-prod')
|
|
702
|
+
// ... rest of operations
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
#### Option 3: Standalone Vector Client
|
|
706
|
+
|
|
707
|
+
For vector-only applications that don't need regular file storage operations:
|
|
708
|
+
|
|
709
|
+
```typescript
|
|
710
|
+
import { StorageVectorsClient } from '@supabase/storage-js'
|
|
711
|
+
|
|
712
|
+
// Initialize standalone vector client
|
|
713
|
+
const vectorClient = new StorageVectorsClient('https://your-project.supabase.co/storage/v1', {
|
|
714
|
+
headers: { Authorization: 'Bearer YOUR_TOKEN' },
|
|
715
|
+
})
|
|
716
|
+
|
|
717
|
+
// Use the same API as shown in Option 1
|
|
718
|
+
await vectorClient.createBucket('embeddings-prod')
|
|
719
|
+
const bucket = vectorClient.from('embeddings-prod')
|
|
720
|
+
// ... rest of operations
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
> **When to use each approach:**
|
|
724
|
+
>
|
|
725
|
+
> - **Option 1**: When using other Supabase features (auth, database, realtime)
|
|
726
|
+
> - **Option 2**: When working with both file storage and vectors
|
|
727
|
+
> - **Option 3**: For dedicated vector-only applications without file storage
|
|
728
|
+
|
|
729
|
+
### API Reference
|
|
730
|
+
|
|
731
|
+
#### Client Initialization
|
|
732
|
+
|
|
733
|
+
```typescript
|
|
734
|
+
const vectorClient = new StorageVectorsClient(url, options?)
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
**Options:**
|
|
738
|
+
|
|
739
|
+
- `headers?: Record<string, string>` - Custom HTTP headers (e.g., Authorization)
|
|
740
|
+
- `fetch?: Fetch` - Custom fetch implementation
|
|
741
|
+
|
|
742
|
+
#### Vector Buckets
|
|
743
|
+
|
|
744
|
+
Vector buckets are top-level containers for organizing vector indexes.
|
|
745
|
+
|
|
746
|
+
##### Create Bucket
|
|
747
|
+
|
|
748
|
+
```typescript
|
|
749
|
+
const { data, error } = await vectorClient.createBucket('my-bucket')
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
##### Get Bucket
|
|
753
|
+
|
|
754
|
+
```typescript
|
|
755
|
+
const { data, error } = await vectorClient.getBucket('my-bucket')
|
|
756
|
+
console.log('Created at:', new Date(data.vectorBucket.creationTime! * 1000))
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
##### List Buckets
|
|
760
|
+
|
|
761
|
+
```typescript
|
|
762
|
+
const { data, error } = await vectorClient.listBuckets({
|
|
763
|
+
prefix: 'prod-',
|
|
764
|
+
maxResults: 100,
|
|
765
|
+
})
|
|
766
|
+
|
|
767
|
+
// Pagination
|
|
768
|
+
if (data?.nextToken) {
|
|
769
|
+
const next = await vectorClient.listBuckets({ nextToken: data.nextToken })
|
|
770
|
+
}
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
##### Delete Bucket
|
|
774
|
+
|
|
775
|
+
```typescript
|
|
776
|
+
// Bucket must be empty (all indexes deleted first)
|
|
777
|
+
const { error } = await vectorClient.deleteBucket('my-bucket')
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
#### Vector Indexes
|
|
781
|
+
|
|
782
|
+
Vector indexes define the schema for embeddings including dimension and distance metric.
|
|
783
|
+
|
|
784
|
+
##### Create Index
|
|
785
|
+
|
|
786
|
+
```typescript
|
|
787
|
+
const bucket = vectorClient.from('my-bucket')
|
|
788
|
+
|
|
789
|
+
await bucket.createIndex({
|
|
790
|
+
indexName: 'my-index',
|
|
791
|
+
dataType: 'float32',
|
|
792
|
+
dimension: 1536,
|
|
793
|
+
distanceMetric: 'cosine', // 'cosine' | 'euclidean' | 'dotproduct'
|
|
794
|
+
metadataConfiguration: {
|
|
795
|
+
nonFilterableMetadataKeys: ['raw_text', 'internal_id'],
|
|
796
|
+
},
|
|
797
|
+
})
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
**Distance Metrics:**
|
|
801
|
+
|
|
802
|
+
- `cosine` - Cosine similarity (normalized dot product)
|
|
803
|
+
- `euclidean` - Euclidean distance (L2 norm)
|
|
804
|
+
- `dotproduct` - Dot product similarity
|
|
805
|
+
|
|
806
|
+
##### Get Index
|
|
807
|
+
|
|
808
|
+
```typescript
|
|
809
|
+
const { data, error } = await bucket.getIndex('my-index')
|
|
810
|
+
console.log('Dimension:', data?.index.dimension)
|
|
811
|
+
console.log('Distance metric:', data?.index.distanceMetric)
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
##### List Indexes
|
|
815
|
+
|
|
816
|
+
```typescript
|
|
817
|
+
const { data, error } = await bucket.listIndexes({
|
|
818
|
+
prefix: 'documents-',
|
|
819
|
+
maxResults: 100,
|
|
820
|
+
})
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
##### Delete Index
|
|
824
|
+
|
|
825
|
+
```typescript
|
|
826
|
+
// Deletes index and all its vectors
|
|
827
|
+
await bucket.deleteIndex('my-index')
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
#### Vector Operations
|
|
831
|
+
|
|
832
|
+
##### Insert/Update Vectors (Upsert)
|
|
833
|
+
|
|
834
|
+
```typescript
|
|
835
|
+
const index = vectorClient.from('my-bucket').index('my-index')
|
|
836
|
+
|
|
837
|
+
await index.putVectors({
|
|
838
|
+
vectors: [
|
|
839
|
+
{
|
|
840
|
+
key: 'unique-id-1',
|
|
841
|
+
data: {
|
|
842
|
+
float32: [
|
|
843
|
+
/* 1536 numbers */
|
|
844
|
+
],
|
|
845
|
+
},
|
|
846
|
+
metadata: {
|
|
847
|
+
title: 'Document Title',
|
|
848
|
+
category: 'technical',
|
|
849
|
+
page: 1,
|
|
850
|
+
},
|
|
851
|
+
},
|
|
852
|
+
// ... up to 500 vectors per request
|
|
853
|
+
],
|
|
854
|
+
})
|
|
855
|
+
```
|
|
856
|
+
|
|
857
|
+
**Limitations:**
|
|
858
|
+
|
|
859
|
+
- 1-500 vectors per request
|
|
860
|
+
- Vectors must match index dimension
|
|
861
|
+
- Keys must be unique within index
|
|
862
|
+
|
|
863
|
+
##### Get Vectors by Key
|
|
864
|
+
|
|
865
|
+
```typescript
|
|
866
|
+
const { data, error } = await index.getVectors({
|
|
867
|
+
keys: ['doc-1', 'doc-2', 'doc-3'],
|
|
868
|
+
returnData: true, // Include embeddings
|
|
869
|
+
returnMetadata: true, // Include metadata
|
|
870
|
+
})
|
|
871
|
+
|
|
872
|
+
data?.vectors.forEach((v) => {
|
|
873
|
+
console.log(v.key, v.metadata)
|
|
874
|
+
})
|
|
875
|
+
```
|
|
876
|
+
|
|
877
|
+
##### Query Similar Vectors (ANN Search)
|
|
878
|
+
|
|
879
|
+
```typescript
|
|
880
|
+
const { data, error } = await index.queryVectors({
|
|
881
|
+
queryVector: {
|
|
882
|
+
float32: [
|
|
883
|
+
/* 1536 numbers */
|
|
884
|
+
],
|
|
885
|
+
},
|
|
886
|
+
topK: 10,
|
|
887
|
+
filter: {
|
|
888
|
+
category: 'technical',
|
|
889
|
+
published: true,
|
|
890
|
+
},
|
|
891
|
+
returnDistance: true,
|
|
892
|
+
returnMetadata: true,
|
|
893
|
+
})
|
|
894
|
+
|
|
895
|
+
// Results ordered by similarity
|
|
896
|
+
data?.matches.forEach((match) => {
|
|
897
|
+
console.log(`${match.key}: distance=${match.distance}`)
|
|
898
|
+
})
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
**Filter Syntax:**
|
|
902
|
+
The `filter` parameter accepts arbitrary JSON for metadata filtering. Non-filterable keys (configured at index creation) cannot be used in filters but can still be returned.
|
|
903
|
+
|
|
904
|
+
##### List/Scan Vectors
|
|
905
|
+
|
|
906
|
+
```typescript
|
|
907
|
+
// Simple pagination
|
|
908
|
+
let nextToken: string | undefined
|
|
909
|
+
do {
|
|
910
|
+
const { data } = await index.listVectors({
|
|
911
|
+
maxResults: 500,
|
|
912
|
+
nextToken,
|
|
913
|
+
returnMetadata: true,
|
|
914
|
+
})
|
|
915
|
+
|
|
916
|
+
console.log('Batch:', data?.vectors.length)
|
|
917
|
+
nextToken = data?.nextToken
|
|
918
|
+
} while (nextToken)
|
|
919
|
+
|
|
920
|
+
// Parallel scanning (4 workers)
|
|
921
|
+
const workers = [0, 1, 2, 3].map(async (segmentIndex) => {
|
|
922
|
+
const { data } = await index.listVectors({
|
|
923
|
+
segmentCount: 4,
|
|
924
|
+
segmentIndex,
|
|
925
|
+
returnMetadata: true,
|
|
926
|
+
})
|
|
927
|
+
return data?.vectors || []
|
|
928
|
+
})
|
|
929
|
+
|
|
930
|
+
const results = await Promise.all(workers)
|
|
931
|
+
const allVectors = results.flat()
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
**Limitations:**
|
|
935
|
+
|
|
936
|
+
- `maxResults`: 1-1000 (default: 500)
|
|
937
|
+
- `segmentCount`: 1-16
|
|
938
|
+
- Response may be limited by 1MB size
|
|
939
|
+
|
|
940
|
+
##### Delete Vectors
|
|
941
|
+
|
|
942
|
+
```typescript
|
|
943
|
+
await index.deleteVectors({
|
|
944
|
+
keys: ['doc-1', 'doc-2', 'doc-3'],
|
|
945
|
+
// ... up to 500 keys per request
|
|
946
|
+
})
|
|
947
|
+
```
|
|
948
|
+
|
|
949
|
+
### Error Handling
|
|
950
|
+
|
|
951
|
+
The library uses a consistent error handling pattern:
|
|
952
|
+
|
|
953
|
+
```typescript
|
|
954
|
+
const { data, error } = await vectorClient.createBucket('my-bucket')
|
|
955
|
+
|
|
956
|
+
if (error) {
|
|
957
|
+
console.error('Error:', error.message)
|
|
958
|
+
console.error('Status:', error.status)
|
|
959
|
+
console.error('Code:', error.statusCode)
|
|
960
|
+
}
|
|
961
|
+
```
|
|
962
|
+
|
|
963
|
+
#### Error Codes
|
|
964
|
+
|
|
965
|
+
| Code | HTTP | Description |
|
|
966
|
+
| ---------------------------- | ---- | ----------------------- |
|
|
967
|
+
| `InternalError` | 500 | Internal server error |
|
|
968
|
+
| `S3VectorConflictException` | 409 | Resource already exists |
|
|
969
|
+
| `S3VectorNotFoundException` | 404 | Resource not found |
|
|
970
|
+
| `S3VectorBucketNotEmpty` | 400 | Bucket contains indexes |
|
|
971
|
+
| `S3VectorMaxBucketsExceeded` | 400 | Bucket quota exceeded |
|
|
972
|
+
| `S3VectorMaxIndexesExceeded` | 400 | Index quota exceeded |
|
|
973
|
+
|
|
974
|
+
#### Throwing Errors
|
|
975
|
+
|
|
976
|
+
You can configure the client to throw errors instead:
|
|
977
|
+
|
|
978
|
+
```typescript
|
|
979
|
+
const vectorClient = new StorageVectorsClient(url, options)
|
|
980
|
+
vectorClient.throwOnError()
|
|
981
|
+
|
|
982
|
+
try {
|
|
983
|
+
const { data } = await vectorClient.createBucket('my-bucket')
|
|
984
|
+
// data is guaranteed to be present
|
|
985
|
+
} catch (error) {
|
|
986
|
+
if (error instanceof StorageVectorsApiError) {
|
|
987
|
+
console.error('API Error:', error.statusCode)
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
```
|
|
991
|
+
|
|
992
|
+
### Advanced Usage
|
|
993
|
+
|
|
994
|
+
#### Scoped Clients
|
|
995
|
+
|
|
996
|
+
Create scoped clients for cleaner code:
|
|
997
|
+
|
|
998
|
+
```typescript
|
|
999
|
+
// Bucket-scoped operations
|
|
1000
|
+
const bucket = vectorClient.from('embeddings-prod')
|
|
1001
|
+
await bucket.createIndex({
|
|
1002
|
+
/* ... */
|
|
1003
|
+
})
|
|
1004
|
+
await bucket.listIndexes()
|
|
1005
|
+
|
|
1006
|
+
// Index-scoped operations
|
|
1007
|
+
const index = bucket.index('documents-openai')
|
|
1008
|
+
await index.putVectors({
|
|
1009
|
+
/* ... */
|
|
1010
|
+
})
|
|
1011
|
+
await index.queryVectors({
|
|
1012
|
+
/* ... */
|
|
1013
|
+
})
|
|
1014
|
+
```
|
|
1015
|
+
|
|
1016
|
+
#### Custom Fetch
|
|
1017
|
+
|
|
1018
|
+
Provide a custom fetch implementation:
|
|
1019
|
+
|
|
1020
|
+
```typescript
|
|
1021
|
+
import { StorageVectorsClient } from '@supabase/storage-js'
|
|
1022
|
+
|
|
1023
|
+
const vectorClient = new StorageVectorsClient(url, {
|
|
1024
|
+
fetch: customFetch,
|
|
1025
|
+
headers: {
|
|
1026
|
+
/* ... */
|
|
1027
|
+
},
|
|
1028
|
+
})
|
|
1029
|
+
```
|
|
1030
|
+
|
|
1031
|
+
#### Batch Processing
|
|
1032
|
+
|
|
1033
|
+
Process large datasets in batches:
|
|
1034
|
+
|
|
1035
|
+
```typescript
|
|
1036
|
+
async function insertLargeDataset(vectors: VectorObject[]) {
|
|
1037
|
+
const batchSize = 500
|
|
1038
|
+
|
|
1039
|
+
for (let i = 0; i < vectors.length; i += batchSize) {
|
|
1040
|
+
const batch = vectors.slice(i, i + batchSize)
|
|
1041
|
+
await index.putVectors({ vectors: batch })
|
|
1042
|
+
console.log(`Inserted ${i + batch.length}/${vectors.length}`)
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
```
|
|
1046
|
+
|
|
1047
|
+
#### Float32 Validation
|
|
1048
|
+
|
|
1049
|
+
Ensure vectors are properly normalized to float32:
|
|
1050
|
+
|
|
1051
|
+
```typescript
|
|
1052
|
+
import { normalizeToFloat32 } from '@supabase/storage-js'
|
|
1053
|
+
|
|
1054
|
+
const vector = normalizeToFloat32([0.1, 0.2, 0.3 /* ... */])
|
|
1055
|
+
```
|
|
1056
|
+
|
|
1057
|
+
### Type Definitions
|
|
1058
|
+
|
|
1059
|
+
The library exports comprehensive TypeScript types:
|
|
1060
|
+
|
|
1061
|
+
```typescript
|
|
1062
|
+
import type {
|
|
1063
|
+
VectorBucket,
|
|
1064
|
+
VectorIndex,
|
|
1065
|
+
VectorData,
|
|
1066
|
+
VectorObject,
|
|
1067
|
+
VectorMatch,
|
|
1068
|
+
VectorMetadata,
|
|
1069
|
+
DistanceMetric,
|
|
1070
|
+
ApiResponse,
|
|
1071
|
+
StorageVectorsError,
|
|
1072
|
+
} from '@supabase/storage-js'
|
|
1073
|
+
```
|
|
1074
|
+
|
|
159
1075
|
## Development
|
|
160
1076
|
|
|
161
|
-
This package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/js
|
|
1077
|
+
This package is part of the [Supabase JavaScript monorepo](https://github.com/supabase/supabase-js). To work on this package:
|
|
162
1078
|
|
|
163
1079
|
### Building
|
|
164
1080
|
|
|
@@ -173,7 +1089,6 @@ The storage-js package uses multiple build scripts to generate different module
|
|
|
173
1089
|
| `build:module` | **ES Modules build** | `dist/module/` - Modern ES6 modules with TypeScript definitions |
|
|
174
1090
|
| `build:umd` | **UMD build** | `dist/umd/` - Universal Module Definition for browsers/CDN |
|
|
175
1091
|
| `clean` | **Clean build artifacts** | Removes `dist/` and `docs/v2/` directories |
|
|
176
|
-
| `format` | **Format code** | Runs Prettier on all TypeScript files |
|
|
177
1092
|
|
|
178
1093
|
#### Running Builds
|
|
179
1094
|
|
|
@@ -392,7 +1307,7 @@ The test infrastructure (`infra/docker-compose.yml`) includes:
|
|
|
392
1307
|
|
|
393
1308
|
#### What About Supabase CLI?
|
|
394
1309
|
|
|
395
|
-
**No**, you don't need `supabase start` or a regular Supabase instance for these tests. The storage-js tests use their own specialized Docker setup that's lighter and focused specifically on testing the storage
|
|
1310
|
+
**No**, you don't need `supabase start` or a regular Supabase instance for these tests. The storage-js tests use their own specialized Docker setup that's lighter and focused specifically on testing the storage SDK. This test infrastructure:
|
|
396
1311
|
|
|
397
1312
|
- Is completely independent from any Supabase CLI projects
|
|
398
1313
|
- Uses fixed test authentication keys
|
|
@@ -402,12 +1317,6 @@ The test infrastructure (`infra/docker-compose.yml`) includes:
|
|
|
402
1317
|
|
|
403
1318
|
### Contributing
|
|
404
1319
|
|
|
405
|
-
We welcome contributions! Please see our [Contributing Guide](../../../
|
|
1320
|
+
We welcome contributions! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details on how to get started.
|
|
406
1321
|
|
|
407
1322
|
For major changes or if you're unsure about something, please open an issue first to discuss your proposed changes.
|
|
408
|
-
|
|
409
|
-
## Sponsors
|
|
410
|
-
|
|
411
|
-
We are building the features of Firebase using enterprise-grade, open source products. We support existing communities wherever possible, and if the products don’t exist we build them and open source them ourselves. Thanks to these sponsors who are making the OSS ecosystem better for everyone.
|
|
412
|
-
|
|
413
|
-
[](https://github.com/sponsors/supabase)
|