diff --git a/packages/firebase/index.d.ts b/packages/firebase/index.d.ts index c0d71742d59..420e8b2eb7b 100644 --- a/packages/firebase/index.d.ts +++ b/packages/firebase/index.d.ts @@ -7617,6 +7617,19 @@ declare namespace firebase.storage { md5Hash?: string | null; } + /** + * An error returned by the Firebase Storage SDK. + */ + interface FirebaseStorageError extends FirebaseError { + serverResponse: string | null; + } + + interface StorageObserver { + next?: NextFn | null; + error?: (error: FirebaseStorageError) => void | null; + complete?: CompleteFn | null; + } + /** * Represents the process of uploading an object. Allows you to monitor and * manage the upload. @@ -7630,7 +7643,7 @@ declare namespace firebase.storage { /** * Equivalent to calling `then(null, onRejected)`. */ - catch(onRejected: (a: Error) => any): Promise; + catch(onRejected: (error: FirebaseStorageError) => any): Promise; /** * Listens for events on this task. * @@ -7730,7 +7743,7 @@ declare namespace firebase.storage { * The `next` function, which gets called for each item in * the event stream, or an observer object with some or all of these three * properties (`next`, `error`, `complete`). - * @param error A function that gets called with an Error + * @param error A function that gets called with a `FirebaseStorageError` * if the event stream ends due to an error. * @param complete A function that gets called if the * event stream ends normally. @@ -7743,10 +7756,10 @@ declare namespace firebase.storage { on( event: firebase.storage.TaskEvent, nextOrObserver?: - | Partial> + | StorageObserver | null - | ((a: UploadTaskSnapshot) => any), - error?: ((a: Error) => any) | null, + | ((snapshot: UploadTaskSnapshot) => any), + error?: ((error: FirebaseStorageError) => any) | null, complete?: firebase.Unsubscribe | null ): Function; /** @@ -7771,8 +7784,10 @@ declare namespace firebase.storage { * @param onRejected The rejection callback. */ then( - onFulfilled?: ((a: firebase.storage.UploadTaskSnapshot) => any) | null, - onRejected?: ((a: Error) => any) | null + onFulfilled?: + | ((snapshot: firebase.storage.UploadTaskSnapshot) => any) + | null, + onRejected?: ((error: FirebaseStorageError) => any) | null ): Promise; } diff --git a/packages/storage-types/index.d.ts b/packages/storage-types/index.d.ts index 902461581cc..5bd2b98dc05 100644 --- a/packages/storage-types/index.d.ts +++ b/packages/storage-types/index.d.ts @@ -15,8 +15,8 @@ * limitations under the License. */ -import { FirebaseApp, FirebaseNamespace } from '@firebase/app-types'; -import { Observer, Unsubscribe } from '@firebase/util'; +import { FirebaseApp } from '@firebase/app-types'; +import { CompleteFn, FirebaseError, NextFn, Unsubscribe } from '@firebase/util'; export interface FullMetadata extends UploadMetadata { bucket: string; @@ -48,7 +48,7 @@ export interface Reference { metadata?: UploadMetadata ): UploadTask; root: Reference; - storage: Storage; + storage: FirebaseStorage; toString(): string; updateMetadata(metadata: SettableMetadata): Promise; listAll(): Promise; @@ -85,24 +85,34 @@ export interface UploadMetadata extends SettableMetadata { md5Hash?: string | null; } +interface FirebaseStorageError extends FirebaseError { + serverResponse: string | null; +} + +export interface StorageObserver { + next?: NextFn | null; + error?: (error: FirebaseStorageError) => void | null; + complete?: CompleteFn | null; +} + export interface UploadTask { cancel(): boolean; - catch(onRejected: (a: Error) => any): Promise; + catch(onRejected: (error: FirebaseStorageError) => any): Promise; on( event: TaskEvent, nextOrObserver?: - | Partial> + | StorageObserver | null - | ((a: UploadTaskSnapshot) => any), - error?: ((a: Error) => any) | null, + | ((snapshot: UploadTaskSnapshot) => any), + error?: ((a: FirebaseStorageError) => any) | null, complete?: Unsubscribe | null ): Function; pause(): boolean; resume(): boolean; snapshot: UploadTaskSnapshot; then( - onFulfilled?: ((a: UploadTaskSnapshot) => any) | null, - onRejected?: ((a: Error) => any) | null + onFulfilled?: ((snapshot: UploadTaskSnapshot) => any) | null, + onRejected?: ((error: FirebaseStorageError) => any) | null ): Promise; } diff --git a/packages/storage/src/implementation/error.ts b/packages/storage/src/implementation/error.ts index 98341b71922..47780c177af 100644 --- a/packages/storage/src/implementation/error.ts +++ b/packages/storage/src/implementation/error.ts @@ -1,3 +1,4 @@ +import { FirebaseError } from '@firebase/util'; /** * @license * Copyright 2017 Google LLC @@ -16,53 +17,34 @@ */ import { CONFIG_STORAGE_BUCKET_KEY } from './constants'; -export class FirebaseStorageError implements Error { - private code_: string; - private message_: string; - private serverResponse_: string | null; - private name_: string; +export class FirebaseStorageError extends FirebaseError { + customData: { serverResponse: string | null } = { serverResponse: null }; constructor(code: Code, message: string) { - this.code_ = prependCode(code); - this.message_ = 'Firebase Storage: ' + message; - this.serverResponse_ = null; - this.name_ = 'FirebaseError'; - } - - codeProp(): string { - return this.code; + super(prependCode(code), 'Firebase Storage: ' + message); + // Without this, `instanceof FirebaseStorageError`, in tests for example, + // returns false. + Object.setPrototypeOf(this, FirebaseStorageError.prototype); } codeEquals(code: Code): boolean { - return prependCode(code) === this.codeProp(); - } - - serverResponseProp(): string | null { - return this.serverResponse_; - } - - setServerResponseProp(serverResponse: string | null): void { - this.serverResponse_ = serverResponse; - } - - get name(): string { - return this.name_; - } - - get code(): string { - return this.code_; + return prependCode(code) === this.code; } get message(): string { - if (this.serverResponse_) { - return this.message_ + '\n' + this.serverResponse_; + if (this.customData.serverResponse) { + return this.message + '\n' + this.customData.serverResponse; } else { - return this.message_; + return this.message; } } get serverResponse(): null | string { - return this.serverResponse_; + return this.customData.serverResponse; + } + + set serverResponse(serverResponse: string | null) { + this.customData.serverResponse = serverResponse; } } diff --git a/packages/storage/src/implementation/request.ts b/packages/storage/src/implementation/request.ts index 90868eb6a55..5b553ad3af8 100644 --- a/packages/storage/src/implementation/request.ts +++ b/packages/storage/src/implementation/request.ts @@ -188,7 +188,7 @@ class NetworkRequest implements Request { } else { if (xhr !== null) { const err = unknown(); - err.setServerResponseProp(xhr.getResponseText()); + err.serverResponse = xhr.getResponseText(); if (self.errorCallback_) { reject(self.errorCallback_(xhr, err)); } else { diff --git a/packages/storage/src/implementation/requests.ts b/packages/storage/src/implementation/requests.ts index 6eeb75de161..8b1fe288e25 100644 --- a/packages/storage/src/implementation/requests.ts +++ b/packages/storage/src/implementation/requests.ts @@ -114,7 +114,7 @@ export function sharedErrorHandler( } } } - newErr.setServerResponseProp(err.serverResponseProp()); + newErr.serverResponse = err.serverResponse; return newErr; } return errorHandler; @@ -133,7 +133,7 @@ export function objectErrorHandler( if (xhr.getStatus() === 404) { newErr = objectNotFound(location.path); } - newErr.setServerResponseProp(err.serverResponseProp()); + newErr.serverResponse = err.serverResponse; return newErr; } return errorHandler;