File size: 5,158 Bytes
96c8713
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/**
 * Namespace type for error classes
 * Determines the error class names and type guards
 */
export type ErrorNamespace = 'storage' | 'vectors'

/**
 * Base error class for all Storage errors
 * Supports both 'storage' and 'vectors' namespaces
 */
export class StorageError extends Error {
  protected __isStorageError = true
  protected namespace: ErrorNamespace
  status: number | undefined
  statusCode: string | undefined

  constructor(
    message: string,
    namespace: ErrorNamespace = 'storage',
    status?: number,
    statusCode?: string
  ) {
    super(message)
    this.namespace = namespace
    this.name = namespace === 'vectors' ? 'StorageVectorsError' : 'StorageError'
    this.status = status
    this.statusCode = statusCode
  }

  toJSON(): {
    name: string
    message: string
    status: number | undefined
    statusCode: string | undefined
  } {
    return {
      name: this.name,
      message: this.message,
      status: this.status,
      statusCode: this.statusCode,
    }
  }
}

/**
 * Type guard to check if an error is a StorageError
 * @param error - The error to check
 * @returns True if the error is a StorageError
 */
export function isStorageError(error: unknown): error is StorageError {
  return typeof error === 'object' && error !== null && '__isStorageError' in error
}

/**
 * API error returned from Storage service
 * Includes HTTP status code and service-specific error code
 */
export class StorageApiError extends StorageError {
  override status: number
  override statusCode: string
  /**
   * Service-specific error code from the Storage API response body, such as
   * `NoSuchKey`, `AccessDenied` or `ResourceAlreadyExists`. Use this to branch
   * on the specific error rather than parsing the message.
   * @see https://supabase.com/docs/guides/storage/debugging/error-codes
   */
  code: string | undefined

  constructor(
    message: string,
    status: number,
    statusCode: string,
    namespace: ErrorNamespace = 'storage',
    code?: string
  ) {
    super(message, namespace, status, statusCode)
    this.name = namespace === 'vectors' ? 'StorageVectorsApiError' : 'StorageApiError'
    this.status = status
    this.statusCode = statusCode
    this.code = code
  }

  toJSON(): {
    name: string
    message: string
    status: number | undefined
    statusCode: string | undefined
    code: string | undefined
  } {
    return {
      ...super.toJSON(),
      code: this.code,
    }
  }
}

/**
 * Unknown error that doesn't match expected error patterns
 * Wraps the original error for debugging
 */
export class StorageUnknownError extends StorageError {
  originalError: unknown

  constructor(message: string, originalError: unknown, namespace: ErrorNamespace = 'storage') {
    super(message, namespace)
    this.name = namespace === 'vectors' ? 'StorageVectorsUnknownError' : 'StorageUnknownError'
    this.originalError = originalError
  }
}

// ============================================================================
// Backward Compatibility Exports for Vectors
// ============================================================================

/**
 * @deprecated Use StorageError with namespace='vectors' instead
 * Alias for backward compatibility with existing vector storage code
 */
export class StorageVectorsError extends StorageError {
  constructor(message: string) {
    super(message, 'vectors')
  }
}

/**
 * Type guard to check if an error is a StorageVectorsError
 * @param error - The error to check
 * @returns True if the error is a StorageVectorsError
 */
export function isStorageVectorsError(error: unknown): error is StorageVectorsError {
  return isStorageError(error) && (error as StorageError)['namespace'] === 'vectors'
}

/**
 * @deprecated Use StorageApiError with namespace='vectors' instead
 * Alias for backward compatibility with existing vector storage code
 */
export class StorageVectorsApiError extends StorageApiError {
  constructor(message: string, status: number, statusCode: string) {
    super(message, status, statusCode, 'vectors')
  }
}

/**
 * @deprecated Use StorageUnknownError with namespace='vectors' instead
 * Alias for backward compatibility with existing vector storage code
 */
export class StorageVectorsUnknownError extends StorageUnknownError {
  constructor(message: string, originalError: unknown) {
    super(message, originalError, 'vectors')
  }
}

/**
 * Error codes specific to S3 Vectors API
 * Maps AWS service errors to application-friendly error codes
 */
export enum StorageVectorsErrorCode {
  /** Internal server fault (HTTP 500) */
  InternalError = 'InternalError',
  /** Resource already exists / conflict (HTTP 409) */
  S3VectorConflictException = 'S3VectorConflictException',
  /** Resource not found (HTTP 404) */
  S3VectorNotFoundException = 'S3VectorNotFoundException',
  /** Delete bucket while not empty (HTTP 400) */
  S3VectorBucketNotEmpty = 'S3VectorBucketNotEmpty',
  /** Exceeds bucket quota/limit (HTTP 400) */
  S3VectorMaxBucketsExceeded = 'S3VectorMaxBucketsExceeded',
  /** Exceeds index quota/limit (HTTP 400) */
  S3VectorMaxIndexesExceeded = 'S3VectorMaxIndexesExceeded',
}