@supabase/storage-js 2.91.1 → 2.91.2

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.
Files changed (38) hide show
  1. package/dist/index.cjs +476 -865
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +1441 -1491
  4. package/dist/index.d.cts.map +1 -1
  5. package/dist/index.d.mts +1441 -1491
  6. package/dist/index.d.mts.map +1 -1
  7. package/dist/index.mjs +477 -861
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/umd/supabase.js +1 -1
  10. package/package.json +1 -1
  11. package/src/StorageClient.ts +2 -2
  12. package/src/index.ts +15 -2
  13. package/src/lib/common/BaseApiClient.ts +90 -0
  14. package/src/lib/common/errors.ts +144 -0
  15. package/src/lib/common/fetch.ts +286 -0
  16. package/src/lib/{helpers.ts → common/helpers.ts} +71 -17
  17. package/src/lib/types.ts +304 -1
  18. package/src/lib/version.ts +1 -1
  19. package/src/packages/BlobDownloadBuilder.ts +1 -1
  20. package/src/packages/StorageAnalyticsClient.ts +17 -68
  21. package/src/packages/StorageBucketApi.ts +25 -109
  22. package/src/packages/StorageFileApi.ts +44 -172
  23. package/src/{lib/vectors → packages}/StorageVectorsClient.ts +2 -2
  24. package/src/packages/StreamDownloadBuilder.ts +1 -1
  25. package/src/packages/VectorBucketApi.ts +73 -0
  26. package/src/packages/VectorDataApi.ts +98 -0
  27. package/src/{lib/vectors → packages}/VectorIndexApi.ts +21 -66
  28. package/src/lib/errors.ts +0 -43
  29. package/src/lib/fetch.ts +0 -148
  30. package/src/lib/index.ts +0 -5
  31. package/src/lib/vectors/VectorBucketApi.ts +0 -118
  32. package/src/lib/vectors/VectorDataApi.ts +0 -152
  33. package/src/lib/vectors/constants.ts +0 -5
  34. package/src/lib/vectors/errors.ts +0 -78
  35. package/src/lib/vectors/fetch.ts +0 -218
  36. package/src/lib/vectors/helpers.ts +0 -79
  37. package/src/lib/vectors/index.ts +0 -66
  38. package/src/lib/vectors/types.ts +0 -301
@@ -1,6 +1,7 @@
1
- import { isStorageError, StorageError, StorageUnknownError } from '../lib/errors'
2
- import { Fetch, get, head, post, put, remove } from '../lib/fetch'
3
- import { recursiveToCamel, resolveFetch } from '../lib/helpers'
1
+ import { StorageError, StorageUnknownError, isStorageError } from '../lib/common/errors'
2
+ import { get, head, post, put, remove, Fetch } from '../lib/common/fetch'
3
+ import { recursiveToCamel } from '../lib/common/helpers'
4
+ import BaseApiClient from '../lib/common/BaseApiClient'
4
5
  import {
5
6
  FileObject,
6
7
  FileOptions,
@@ -42,12 +43,8 @@ type FileBody =
42
43
  | URLSearchParams
43
44
  | string
44
45
 
45
- export default class StorageFileApi {
46
- protected url: string
47
- protected headers: { [key: string]: string }
46
+ export default class StorageFileApi extends BaseApiClient<StorageError> {
48
47
  protected bucketId?: string
49
- protected fetch: Fetch
50
- protected shouldThrowOnError = false
51
48
 
52
49
  constructor(
53
50
  url: string,
@@ -55,20 +52,8 @@ export default class StorageFileApi {
55
52
  bucketId?: string,
56
53
  fetch?: Fetch
57
54
  ) {
58
- this.url = url
59
- this.headers = headers
55
+ super(url, headers, fetch, 'storage')
60
56
  this.bucketId = bucketId
61
- this.fetch = resolveFetch(fetch)
62
- }
63
-
64
- /**
65
- * Enable throwing errors instead of returning them.
66
- *
67
- * @category File Buckets
68
- */
69
- public throwOnError(): this {
70
- this.shouldThrowOnError = true
71
- return this
72
57
  }
73
58
 
74
59
  /**
@@ -93,7 +78,7 @@ export default class StorageFileApi {
93
78
  error: StorageError
94
79
  }
95
80
  > {
96
- try {
81
+ return this.handleOperation(async () => {
97
82
  let body
98
83
  const options = { ...DEFAULT_FILE_OPTIONS, ...fileOptions }
99
84
  let headers: Record<string, string> = {
@@ -152,20 +137,8 @@ export default class StorageFileApi {
152
137
  { headers, ...(options?.duplex ? { duplex: options.duplex } : {}) }
153
138
  )
154
139
 
155
- return {
156
- data: { path: cleanPath, id: data.Id, fullPath: data.Key },
157
- error: null,
158
- }
159
- } catch (error) {
160
- if (this.shouldThrowOnError) {
161
- throw error
162
- }
163
- if (isStorageError(error)) {
164
- return { data: null, error }
165
- }
166
-
167
- throw error
168
- }
140
+ return { path: cleanPath, id: data.Id, fullPath: data.Key }
141
+ })
169
142
  }
170
143
 
171
144
  /**
@@ -272,7 +245,7 @@ export default class StorageFileApi {
272
245
  const url = new URL(this.url + `/object/upload/sign/${_path}`)
273
246
  url.searchParams.set('token', token)
274
247
 
275
- try {
248
+ return this.handleOperation(async () => {
276
249
  let body
277
250
  const options = { upsert: DEFAULT_FILE_OPTIONS.upsert, ...fileOptions }
278
251
  const headers: Record<string, string> = {
@@ -295,20 +268,8 @@ export default class StorageFileApi {
295
268
 
296
269
  const data = await put(this.fetch, url.toString(), body as object, { headers })
297
270
 
298
- return {
299
- data: { path: cleanPath, fullPath: data.Key },
300
- error: null,
301
- }
302
- } catch (error) {
303
- if (this.shouldThrowOnError) {
304
- throw error
305
- }
306
- if (isStorageError(error)) {
307
- return { data: null, error }
308
- }
309
-
310
- throw error
311
- }
271
+ return { path: cleanPath, fullPath: data.Key }
272
+ })
312
273
  }
313
274
 
314
275
  /**
@@ -354,7 +315,7 @@ export default class StorageFileApi {
354
315
  error: StorageError
355
316
  }
356
317
  > {
357
- try {
318
+ return this.handleOperation(async () => {
358
319
  let _path = this._getFinalPath(path)
359
320
 
360
321
  const headers = { ...this.headers }
@@ -378,17 +339,8 @@ export default class StorageFileApi {
378
339
  throw new StorageError('No token returned by API')
379
340
  }
380
341
 
381
- return { data: { signedUrl: url.toString(), path, token }, error: null }
382
- } catch (error) {
383
- if (this.shouldThrowOnError) {
384
- throw error
385
- }
386
- if (isStorageError(error)) {
387
- return { data: null, error }
388
- }
389
-
390
- throw error
391
- }
342
+ return { signedUrl: url.toString(), path, token }
343
+ })
392
344
  }
393
345
 
394
346
  /**
@@ -503,8 +455,8 @@ export default class StorageFileApi {
503
455
  error: StorageError
504
456
  }
505
457
  > {
506
- try {
507
- const data = await post(
458
+ return this.handleOperation(async () => {
459
+ return await post(
508
460
  this.fetch,
509
461
  `${this.url}/object/move`,
510
462
  {
@@ -515,17 +467,7 @@ export default class StorageFileApi {
515
467
  },
516
468
  { headers: this.headers }
517
469
  )
518
- return { data, error: null }
519
- } catch (error) {
520
- if (this.shouldThrowOnError) {
521
- throw error
522
- }
523
- if (isStorageError(error)) {
524
- return { data: null, error }
525
- }
526
-
527
- throw error
528
- }
470
+ })
529
471
  }
530
472
 
531
473
  /**
@@ -569,7 +511,7 @@ export default class StorageFileApi {
569
511
  error: StorageError
570
512
  }
571
513
  > {
572
- try {
514
+ return this.handleOperation(async () => {
573
515
  const data = await post(
574
516
  this.fetch,
575
517
  `${this.url}/object/copy`,
@@ -581,17 +523,8 @@ export default class StorageFileApi {
581
523
  },
582
524
  { headers: this.headers }
583
525
  )
584
- return { data: { path: data.Key }, error: null }
585
- } catch (error) {
586
- if (this.shouldThrowOnError) {
587
- throw error
588
- }
589
- if (isStorageError(error)) {
590
- return { data: null, error }
591
- }
592
-
593
- throw error
594
- }
526
+ return { path: data.Key }
527
+ })
595
528
  }
596
529
 
597
530
  /**
@@ -659,7 +592,7 @@ export default class StorageFileApi {
659
592
  error: StorageError
660
593
  }
661
594
  > {
662
- try {
595
+ return this.handleOperation(async () => {
663
596
  let _path = this._getFinalPath(path)
664
597
 
665
598
  let data = await post(
@@ -672,18 +605,8 @@ export default class StorageFileApi {
672
605
  ? `&download=${options.download === true ? '' : options.download}`
673
606
  : ''
674
607
  const signedUrl = encodeURI(`${this.url}${data.signedURL}${downloadQueryParam}`)
675
- data = { signedUrl }
676
- return { data, error: null }
677
- } catch (error) {
678
- if (this.shouldThrowOnError) {
679
- throw error
680
- }
681
- if (isStorageError(error)) {
682
- return { data: null, error }
683
- }
684
-
685
- throw error
686
- }
608
+ return { signedUrl }
609
+ })
687
610
  }
688
611
 
689
612
  /**
@@ -738,7 +661,7 @@ export default class StorageFileApi {
738
661
  error: StorageError
739
662
  }
740
663
  > {
741
- try {
664
+ return this.handleOperation(async () => {
742
665
  const data = await post(
743
666
  this.fetch,
744
667
  `${this.url}/object/sign/${this.bucketId}`,
@@ -749,25 +672,13 @@ export default class StorageFileApi {
749
672
  const downloadQueryParam = options?.download
750
673
  ? `&download=${options.download === true ? '' : options.download}`
751
674
  : ''
752
- return {
753
- data: data.map((datum: { signedURL: string }) => ({
754
- ...datum,
755
- signedUrl: datum.signedURL
756
- ? encodeURI(`${this.url}${datum.signedURL}${downloadQueryParam}`)
757
- : null,
758
- })),
759
- error: null,
760
- }
761
- } catch (error) {
762
- if (this.shouldThrowOnError) {
763
- throw error
764
- }
765
- if (isStorageError(error)) {
766
- return { data: null, error }
767
- }
768
-
769
- throw error
770
- }
675
+ return data.map((datum: { signedURL: string }) => ({
676
+ ...datum,
677
+ signedUrl: datum.signedURL
678
+ ? encodeURI(`${this.url}${datum.signedURL}${downloadQueryParam}`)
679
+ : null,
680
+ }))
681
+ })
771
682
  }
772
683
 
773
684
  /**
@@ -852,22 +763,13 @@ export default class StorageFileApi {
852
763
  > {
853
764
  const _path = this._getFinalPath(path)
854
765
 
855
- try {
766
+ return this.handleOperation(async () => {
856
767
  const data = await get(this.fetch, `${this.url}/object/info/${_path}`, {
857
768
  headers: this.headers,
858
769
  })
859
770
 
860
- return { data: recursiveToCamel(data) as Camelize<FileObjectV2>, error: null }
861
- } catch (error) {
862
- if (this.shouldThrowOnError) {
863
- throw error
864
- }
865
- if (isStorageError(error)) {
866
- return { data: null, error }
867
- }
868
-
869
- throw error
870
- }
771
+ return recursiveToCamel(data) as Camelize<FileObjectV2>
772
+ })
871
773
  }
872
774
 
873
775
  /**
@@ -1035,24 +937,14 @@ export default class StorageFileApi {
1035
937
  error: StorageError
1036
938
  }
1037
939
  > {
1038
- try {
1039
- const data = await remove(
940
+ return this.handleOperation(async () => {
941
+ return await remove(
1040
942
  this.fetch,
1041
943
  `${this.url}/object/${this.bucketId}`,
1042
944
  { prefixes: paths },
1043
945
  { headers: this.headers }
1044
946
  )
1045
- return { data, error: null }
1046
- } catch (error) {
1047
- if (this.shouldThrowOnError) {
1048
- throw error
1049
- }
1050
- if (isStorageError(error)) {
1051
- return { data: null, error }
1052
- }
1053
-
1054
- throw error
1055
- }
947
+ })
1056
948
  }
1057
949
 
1058
950
  /**
@@ -1191,26 +1083,16 @@ export default class StorageFileApi {
1191
1083
  error: StorageError
1192
1084
  }
1193
1085
  > {
1194
- try {
1086
+ return this.handleOperation(async () => {
1195
1087
  const body = { ...DEFAULT_SEARCH_OPTIONS, ...options, prefix: path || '' }
1196
- const data = await post(
1088
+ return await post(
1197
1089
  this.fetch,
1198
1090
  `${this.url}/object/list/${this.bucketId}`,
1199
1091
  body,
1200
1092
  { headers: this.headers },
1201
1093
  parameters
1202
1094
  )
1203
- return { data, error: null }
1204
- } catch (error) {
1205
- if (this.shouldThrowOnError) {
1206
- throw error
1207
- }
1208
- if (isStorageError(error)) {
1209
- return { data: null, error }
1210
- }
1211
-
1212
- throw error
1213
- }
1095
+ })
1214
1096
  }
1215
1097
 
1216
1098
  /**
@@ -1233,26 +1115,16 @@ export default class StorageFileApi {
1233
1115
  error: StorageError
1234
1116
  }
1235
1117
  > {
1236
- try {
1118
+ return this.handleOperation(async () => {
1237
1119
  const body = { ...options }
1238
- const data = await post(
1120
+ return await post(
1239
1121
  this.fetch,
1240
1122
  `${this.url}/object/list-v2/${this.bucketId}`,
1241
1123
  body,
1242
1124
  { headers: this.headers },
1243
1125
  parameters
1244
1126
  )
1245
- return { data, error: null }
1246
- } catch (error) {
1247
- if (this.shouldThrowOnError) {
1248
- throw error
1249
- }
1250
- if (isStorageError(error)) {
1251
- return { data: null, error }
1252
- }
1253
-
1254
- throw error
1255
- }
1127
+ })
1256
1128
  }
1257
1129
 
1258
1130
  protected encodeMetadata(metadata: Record<string, any>) {
@@ -1,6 +1,6 @@
1
1
  import VectorIndexApi, { CreateIndexOptions } from './VectorIndexApi'
2
2
  import VectorDataApi from './VectorDataApi'
3
- import { Fetch } from './fetch'
3
+ import { Fetch } from '../lib/common/fetch'
4
4
  import VectorBucketApi from './VectorBucketApi'
5
5
  import {
6
6
  ApiResponse,
@@ -13,7 +13,7 @@ import {
13
13
  PutVectorsOptions,
14
14
  QueryVectorsOptions,
15
15
  VectorBucket,
16
- } from './types'
16
+ } from '../lib/types'
17
17
 
18
18
  /**
19
19
  *
@@ -1,4 +1,4 @@
1
- import { isStorageError } from '../lib/errors'
1
+ import { isStorageError } from '../lib/common/errors'
2
2
  import { DownloadResult } from '../lib/types'
3
3
 
4
4
  export default class StreamDownloadBuilder implements PromiseLike<DownloadResult<ReadableStream>> {
@@ -0,0 +1,73 @@
1
+ import { DEFAULT_HEADERS } from '../lib/constants'
2
+ import { StorageError } from '../lib/common/errors'
3
+ import { Fetch, post } from '../lib/common/fetch'
4
+ import BaseApiClient from '../lib/common/BaseApiClient'
5
+ import {
6
+ ApiResponse,
7
+ VectorBucket,
8
+ ListVectorBucketsOptions,
9
+ ListVectorBucketsResponse,
10
+ } from '../lib/types'
11
+
12
+ /**
13
+ * @hidden
14
+ * Base implementation for vector bucket operations.
15
+ * Use {@link StorageVectorsClient} via `supabase.storage.vectors` instead.
16
+ */
17
+ export default class VectorBucketApi extends BaseApiClient<StorageError> {
18
+ /** Creates a new VectorBucketApi instance */
19
+ constructor(url: string, headers: { [key: string]: string } = {}, fetch?: Fetch) {
20
+ const finalUrl = url.replace(/\/$/, '')
21
+ const finalHeaders = { ...DEFAULT_HEADERS, 'Content-Type': 'application/json', ...headers }
22
+ super(finalUrl, finalHeaders, fetch, 'vectors')
23
+ }
24
+
25
+ /** Creates a new vector bucket */
26
+ async createBucket(vectorBucketName: string): Promise<ApiResponse<undefined>> {
27
+ return this.handleOperation(async () => {
28
+ const data = await post(
29
+ this.fetch,
30
+ `${this.url}/CreateVectorBucket`,
31
+ { vectorBucketName },
32
+ { headers: this.headers }
33
+ )
34
+ return data || {}
35
+ })
36
+ }
37
+
38
+ /** Retrieves metadata for a specific vector bucket */
39
+ async getBucket(vectorBucketName: string): Promise<ApiResponse<{ vectorBucket: VectorBucket }>> {
40
+ return this.handleOperation(async () => {
41
+ return await post(
42
+ this.fetch,
43
+ `${this.url}/GetVectorBucket`,
44
+ { vectorBucketName },
45
+ { headers: this.headers }
46
+ )
47
+ })
48
+ }
49
+
50
+ /** Lists vector buckets with optional filtering and pagination */
51
+ async listBuckets(
52
+ options: ListVectorBucketsOptions = {}
53
+ ): Promise<ApiResponse<ListVectorBucketsResponse>> {
54
+ return this.handleOperation(async () => {
55
+ return await post(this.fetch, `${this.url}/ListVectorBuckets`, options, {
56
+ headers: this.headers,
57
+ })
58
+ })
59
+ }
60
+
61
+ /** Deletes a vector bucket (must be empty first) */
62
+ async deleteBucket(vectorBucketName: string): Promise<ApiResponse<undefined>> {
63
+ return this.handleOperation(async () => {
64
+ const data = await post(
65
+ this.fetch,
66
+ `${this.url}/DeleteVectorBucket`,
67
+ { vectorBucketName },
68
+ { headers: this.headers }
69
+ )
70
+ return data || {}
71
+ })
72
+ }
73
+ }
@@ -0,0 +1,98 @@
1
+ import { DEFAULT_HEADERS } from '../lib/constants'
2
+ import { StorageError } from '../lib/common/errors'
3
+ import { Fetch, post } from '../lib/common/fetch'
4
+ import BaseApiClient from '../lib/common/BaseApiClient'
5
+ import {
6
+ ApiResponse,
7
+ PutVectorsOptions,
8
+ GetVectorsOptions,
9
+ GetVectorsResponse,
10
+ DeleteVectorsOptions,
11
+ ListVectorsOptions,
12
+ ListVectorsResponse,
13
+ QueryVectorsOptions,
14
+ QueryVectorsResponse,
15
+ } from '../lib/types'
16
+
17
+ /**
18
+ * @hidden
19
+ * Base implementation for vector data operations.
20
+ * Use {@link VectorIndexScope} via `supabase.storage.vectors.from('bucket').index('idx')` instead.
21
+ */
22
+ export default class VectorDataApi extends BaseApiClient<StorageError> {
23
+ /** Creates a new VectorDataApi instance */
24
+ constructor(url: string, headers: { [key: string]: string } = {}, fetch?: Fetch) {
25
+ const finalUrl = url.replace(/\/$/, '')
26
+ const finalHeaders = { ...DEFAULT_HEADERS, 'Content-Type': 'application/json', ...headers }
27
+ super(finalUrl, finalHeaders, fetch, 'vectors')
28
+ }
29
+
30
+ /** Inserts or updates vectors in batch (1-500 per request) */
31
+ async putVectors(options: PutVectorsOptions): Promise<ApiResponse<undefined>> {
32
+ // Validate batch size
33
+ if (options.vectors.length < 1 || options.vectors.length > 500) {
34
+ throw new Error('Vector batch size must be between 1 and 500 items')
35
+ }
36
+
37
+ return this.handleOperation(async () => {
38
+ const data = await post(this.fetch, `${this.url}/PutVectors`, options, {
39
+ headers: this.headers,
40
+ })
41
+ return data || {}
42
+ })
43
+ }
44
+
45
+ /** Retrieves vectors by their keys in batch */
46
+ async getVectors(options: GetVectorsOptions): Promise<ApiResponse<GetVectorsResponse>> {
47
+ return this.handleOperation(async () => {
48
+ return await post(this.fetch, `${this.url}/GetVectors`, options, {
49
+ headers: this.headers,
50
+ })
51
+ })
52
+ }
53
+
54
+ /** Lists vectors in an index with pagination */
55
+ async listVectors(options: ListVectorsOptions): Promise<ApiResponse<ListVectorsResponse>> {
56
+ // Validate segment configuration
57
+ if (options.segmentCount !== undefined) {
58
+ if (options.segmentCount < 1 || options.segmentCount > 16) {
59
+ throw new Error('segmentCount must be between 1 and 16')
60
+ }
61
+ if (options.segmentIndex !== undefined) {
62
+ if (options.segmentIndex < 0 || options.segmentIndex >= options.segmentCount) {
63
+ throw new Error(`segmentIndex must be between 0 and ${options.segmentCount - 1}`)
64
+ }
65
+ }
66
+ }
67
+
68
+ return this.handleOperation(async () => {
69
+ return await post(this.fetch, `${this.url}/ListVectors`, options, {
70
+ headers: this.headers,
71
+ })
72
+ })
73
+ }
74
+
75
+ /** Queries for similar vectors using approximate nearest neighbor search */
76
+ async queryVectors(options: QueryVectorsOptions): Promise<ApiResponse<QueryVectorsResponse>> {
77
+ return this.handleOperation(async () => {
78
+ return await post(this.fetch, `${this.url}/QueryVectors`, options, {
79
+ headers: this.headers,
80
+ })
81
+ })
82
+ }
83
+
84
+ /** Deletes vectors by their keys in batch (1-500 per request) */
85
+ async deleteVectors(options: DeleteVectorsOptions): Promise<ApiResponse<undefined>> {
86
+ // Validate batch size
87
+ if (options.keys.length < 1 || options.keys.length > 500) {
88
+ throw new Error('Keys batch size must be between 1 and 500 items')
89
+ }
90
+
91
+ return this.handleOperation(async () => {
92
+ const data = await post(this.fetch, `${this.url}/DeleteVectors`, options, {
93
+ headers: this.headers,
94
+ })
95
+ return data || {}
96
+ })
97
+ }
98
+ }