diff --git a/packages/storage/src/implementation/connection.ts b/packages/storage/src/implementation/connection.ts index f575a0b29a4..94f46a5a4f5 100644 --- a/packages/storage/src/implementation/connection.ts +++ b/packages/storage/src/implementation/connection.ts @@ -15,12 +15,8 @@ * limitations under the License. */ -/** - * Network headers - */ -export interface Headers { - [name: string]: string; -} +/** Network headers */ +export type Headers = Record; /** * A lightweight wrapper around XMLHttpRequest with a diff --git a/packages/storage/src/implementation/error.ts b/packages/storage/src/implementation/error.ts index dab199db8d6..6d9f3bcb909 100644 --- a/packages/storage/src/implementation/error.ts +++ b/packages/storage/src/implementation/error.ts @@ -312,10 +312,7 @@ export function invalidRootOperation(name: string): StorageError { * @param format - The format that was not valid. * @param message - A message describing the format violation. */ -export function invalidFormat( - format: string, - message: string -): StorageError { +export function invalidFormat(format: string, message: string): StorageError { return new StorageError( StorageErrorCode.INVALID_FORMAT, "String does not match format '" + format + "': " + message @@ -326,10 +323,7 @@ export function invalidFormat( * @param message - A message describing the internal error. */ export function unsupportedEnvironment(message: string): StorageError { - throw new StorageError( - StorageErrorCode.UNSUPPORTED_ENVIRONMENT, - message - ); + throw new StorageError(StorageErrorCode.UNSUPPORTED_ENVIRONMENT, message); } /** diff --git a/packages/storage/src/implementation/request.ts b/packages/storage/src/implementation/request.ts index e7beb9dd5a4..79d09009f75 100644 --- a/packages/storage/src/implementation/request.ts +++ b/packages/storage/src/implementation/request.ts @@ -28,7 +28,7 @@ import { canceled, retryLimitExceeded } from './error'; -import { RequestInfo } from './requestinfo'; +import { RequestHandler, RequestInfo } from './requestinfo'; import { isJustDef } from './type'; import { makeQueryString } from './url'; import { Headers, Connection, ErrorCode } from './connection'; @@ -48,12 +48,6 @@ export interface Request { } class NetworkRequest implements Request { - private url_: string; - private method_: string; - private headers_: Headers; - private body_: string | Blob | Uint8Array | null; - private successCodes_: number[]; - private additionalRetryCodes_: number[]; private pendingConnection_: Connection | null = null; private backoffId_: backoffId | null = null; private resolve_!: (value?: T | PromiseLike) => void; @@ -61,41 +55,21 @@ class NetworkRequest implements Request { private reject_!: (reason?: any) => void; private canceled_: boolean = false; private appDelete_: boolean = false; - private callback_: (p1: Connection, p2: string) => T; - private errorCallback_: - | ((p1: Connection, p2: StorageError) => StorageError) - | null; - private progressCallback_: ((p1: number, p2: number) => void) | null; - private timeout_: number; - private pool_: ConnectionPool; promise_: Promise; constructor( - url: string, - method: string, - headers: Headers, - body: string | Blob | Uint8Array | null, - successCodes: number[], - additionalRetryCodes: number[], - callback: (p1: Connection, p2: string) => T, - errorCallback: - | ((p1: Connection, p2: StorageError) => StorageError) - | null, - timeout: number, - progressCallback: ((p1: number, p2: number) => void) | null, - pool: ConnectionPool + private url_: string, + private method_: string, + private headers_: Headers, + private body_: string | Blob | Uint8Array | null, + private successCodes_: number[], + private additionalRetryCodes_: number[], + private callback_: RequestHandler, + private errorCallback_: RequestHandler | null, + private timeout_: number, + private progressCallback_: ((p1: number, p2: number) => void) | null, + private pool_: ConnectionPool ) { - this.url_ = url; - this.method_ = method; - this.headers_ = headers; - this.body_ = body; - this.successCodes_ = successCodes.slice(); - this.additionalRetryCodes_ = additionalRetryCodes.slice(); - this.callback_ = callback; - this.errorCallback_ = errorCallback; - this.progressCallback_ = progressCallback; - this.timeout_ = timeout; - this.pool_ = pool; this.promise_ = new Promise((resolve, reject) => { this.resolve_ = resolve as (value?: T | PromiseLike) => void; this.reject_ = reject; @@ -107,41 +81,42 @@ class NetworkRequest implements Request { * Actually starts the retry loop. */ private start_(): void { - const self = this; - - function doTheRequest( - backoffCallback: (p1: boolean, ...p2: unknown[]) => void, + const doTheRequest: ( + backoffCallback: (success: boolean, ...p2: unknown[]) => void, canceled: boolean - ): void { + ) => void = (backoffCallback, canceled) => { if (canceled) { backoffCallback(false, new RequestEndStatus(false, null, true)); return; } - const connection = self.pool_.createConnection(); - self.pendingConnection_ = connection; + const connection = this.pool_.createConnection(); + this.pendingConnection_ = connection; - function progressListener(progressEvent: ProgressEvent): void { - const loaded = progressEvent.loaded; - const total = progressEvent.lengthComputable ? progressEvent.total : -1; - if (self.progressCallback_ !== null) { - self.progressCallback_(loaded, total); - } - } - if (self.progressCallback_ !== null) { + const progressListener: (progressEvent: ProgressEvent) => void = + progressEvent => { + const loaded = progressEvent.loaded; + const total = progressEvent.lengthComputable + ? progressEvent.total + : -1; + if (this.progressCallback_ !== null) { + this.progressCallback_(loaded, total); + } + }; + if (this.progressCallback_ !== null) { connection.addUploadProgressListener(progressListener); } // eslint-disable-next-line @typescript-eslint/no-floating-promises connection - .send(self.url_, self.method_, self.body_, self.headers_) + .send(this.url_, this.method_, this.body_, this.headers_) .then(() => { - if (self.progressCallback_ !== null) { + if (this.progressCallback_ !== null) { connection.removeUploadProgressListener(progressListener); } - self.pendingConnection_ = null; + this.pendingConnection_ = null; const hitServer = connection.getErrorCode() === ErrorCode.NO_ERROR; const status = connection.getStatus(); - if (!hitServer || self.isRetryStatusCode_(status)) { + if (!hitServer || this.isRetryStatusCode_(status)) { const wasCanceled = connection.getErrorCode() === ErrorCode.ABORT; backoffCallback( false, @@ -149,25 +124,25 @@ class NetworkRequest implements Request { ); return; } - const successCode = self.successCodes_.indexOf(status) !== -1; + const successCode = this.successCodes_.indexOf(status) !== -1; backoffCallback(true, new RequestEndStatus(successCode, connection)); }); - } + }; /** * @param requestWentThrough - True if the request eventually went * through, false if it hit the retry limit or was canceled. */ - function backoffDone( + const backoffDone: ( requestWentThrough: boolean, status: RequestEndStatus - ): void { - const resolve = self.resolve_; - const reject = self.reject_; + ) => void = (requestWentThrough, status) => { + const resolve = this.resolve_; + const reject = this.reject_; const connection = status.connection as Connection; if (status.wasSuccessCode) { try { - const result = self.callback_( + const result = this.callback_( connection, connection.getResponseText() ); @@ -183,14 +158,14 @@ class NetworkRequest implements Request { if (connection !== null) { const err = unknown(); err.serverResponse = connection.getResponseText(); - if (self.errorCallback_) { - reject(self.errorCallback_(connection, err)); + if (this.errorCallback_) { + reject(this.errorCallback_(connection, err)); } else { reject(err); } } else { if (status.canceled) { - const err = self.appDelete_ ? appDeleted() : canceled(); + const err = this.appDelete_ ? appDeleted() : canceled(); reject(err); } else { const err = retryLimitExceeded(); @@ -198,7 +173,7 @@ class NetworkRequest implements Request { } } } - } + }; if (this.canceled_) { backoffDone(false, new RequestEndStatus(false, null, true)); } else { diff --git a/packages/storage/src/implementation/requestinfo.ts b/packages/storage/src/implementation/requestinfo.ts index 1b9b4ab308a..2451410f826 100644 --- a/packages/storage/src/implementation/requestinfo.ts +++ b/packages/storage/src/implementation/requestinfo.ts @@ -24,14 +24,20 @@ export interface UrlParams { [name: string]: string | number; } +/** + * A function that converts a server response to the API type expected by the + * SDK. + * + * @param I - the type of the backend's network response + * @param O - the output response type used by the rest of the SDK. + */ +export type RequestHandler = (connection: Connection, response: I) => O; + export class RequestInfo { urlParams: UrlParams = {}; headers: Headers = {}; body: Blob | string | Uint8Array | null = null; - - errorHandler: - | ((p1: Connection, p2: StorageError) => StorageError) - | null = null; + errorHandler: RequestHandler | null = null; /** * Called with the current number of bytes uploaded and total size (-1 if not @@ -51,7 +57,7 @@ export class RequestInfo { * Note: The XhrIo passed to this function may be reused after this callback * returns. Do not keep a reference to it in any way. */ - public handler: (p1: Connection, p2: string) => T, + public handler: RequestHandler, public timeout: number ) {} } diff --git a/packages/storage/src/platform/browser/connection.ts b/packages/storage/src/platform/browser/connection.ts index 9b26087779d..093f2425467 100644 --- a/packages/storage/src/platform/browser/connection.ts +++ b/packages/storage/src/platform/browser/connection.ts @@ -50,9 +50,6 @@ export class XhrConnection implements Connection { }); } - /** - * @override - */ send( url: string, method: string, @@ -79,9 +76,6 @@ export class XhrConnection implements Connection { return this.sendPromise_; } - /** - * @override - */ getErrorCode(): ErrorCode { if (!this.sent_) { throw internalError('cannot .getErrorCode() before sending'); @@ -89,9 +83,6 @@ export class XhrConnection implements Connection { return this.errorCode_; } - /** - * @override - */ getStatus(): number { if (!this.sent_) { throw internalError('cannot .getStatus() before sending'); @@ -103,9 +94,6 @@ export class XhrConnection implements Connection { } } - /** - * @override - */ getResponseText(): string { if (!this.sent_) { throw internalError('cannot .getResponseText() before sending'); @@ -113,33 +101,21 @@ export class XhrConnection implements Connection { return this.xhr_.responseText; } - /** - * Aborts the request. - * @override - */ + /** Aborts the request. */ abort(): void { this.xhr_.abort(); } - /** - * @override - */ getResponseHeader(header: string): string | null { return this.xhr_.getResponseHeader(header); } - /** - * @override - */ addUploadProgressListener(listener: (p1: ProgressEvent) => void): void { if (this.xhr_.upload != null) { this.xhr_.upload.addEventListener('progress', listener); } } - /** - * @override - */ removeUploadProgressListener(listener: (p1: ProgressEvent) => void): void { if (this.xhr_.upload != null) { this.xhr_.upload.removeEventListener('progress', listener); diff --git a/packages/storage/src/task.ts b/packages/storage/src/task.ts index 91131f63615..6ba1d861b86 100644 --- a/packages/storage/src/task.ts +++ b/packages/storage/src/task.ts @@ -521,9 +521,7 @@ export class UploadTask { /** * Equivalent to calling `then(null, onRejected)`. */ - catch( - onRejected: (p1: StorageError) => T | Promise - ): Promise { + catch(onRejected: (p1: StorageError) => T | Promise): Promise { return this.then(null, onRejected); } diff --git a/packages/storage/test/unit/connection.ts b/packages/storage/test/unit/connection.ts index 350feaa90bf..24e6cd76044 100644 --- a/packages/storage/test/unit/connection.ts +++ b/packages/storage/test/unit/connection.ts @@ -19,10 +19,7 @@ import { Headers, Connection } from '../../src/implementation/connection'; -import { - StorageError, - StorageErrorCode -} from '../../src/implementation/error'; +import { StorageError, StorageErrorCode } from '../../src/implementation/error'; export type SendHook = ( connection: TestingConnection, @@ -67,10 +64,7 @@ export class TestingConnection implements Connection { headers?: Headers ): Promise { if (this.state !== State.START) { - throw new StorageError( - StorageErrorCode.UNKNOWN, - "Can't send again" - ); + throw new StorageError(StorageErrorCode.UNKNOWN, "Can't send again"); } this.state = State.SENT; diff --git a/packages/storage/test/unit/string.test.ts b/packages/storage/test/unit/string.test.ts index 5e445f9ccb1..3bc35e166e9 100644 --- a/packages/storage/test/unit/string.test.ts +++ b/packages/storage/test/unit/string.test.ts @@ -23,20 +23,8 @@ describe('Firebase Storage > String', () => { const str = 'Hello, world!\n'; assertUint8ArrayEquals( new Uint8Array([ - 0x48, - 0x65, - 0x6c, - 0x6c, - 0x6f, - 0x2c, - 0x20, - 0x77, - 0x6f, - 0x72, - 0x6c, - 0x64, - 0x21, - 0x0a + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, + 0x21, 0x0a ]), dataFromString(StringFormat.RAW, str).data ); @@ -59,17 +47,7 @@ describe('Firebase Storage > String', () => { const str = 'Hello! \ud83d\ude0a'; assertUint8ArrayEquals( new Uint8Array([ - 0x48, - 0x65, - 0x6c, - 0x6c, - 0x6f, - 0x21, - 0x20, - 0xf0, - 0x9f, - 0x98, - 0x8a + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21, 0x20, 0xf0, 0x9f, 0x98, 0x8a ]), dataFromString(StringFormat.RAW, str).data ); @@ -91,26 +69,8 @@ describe('Firebase Storage > String', () => { it('Encodes base64 strings correctly', () => { const str = 'CpYlM1+XsGxTd1n6izHMU/yY3Bw='; const base64Bytes = new Uint8Array([ - 0x0a, - 0x96, - 0x25, - 0x33, - 0x5f, - 0x97, - 0xb0, - 0x6c, - 0x53, - 0x77, - 0x59, - 0xfa, - 0x8b, - 0x31, - 0xcc, - 0x53, - 0xfc, - 0x98, - 0xdc, - 0x1c + 0x0a, 0x96, 0x25, 0x33, 0x5f, 0x97, 0xb0, 0x6c, 0x53, 0x77, 0x59, 0xfa, + 0x8b, 0x31, 0xcc, 0x53, 0xfc, 0x98, 0xdc, 0x1c ]); assertUint8ArrayEquals( base64Bytes, @@ -120,26 +80,8 @@ describe('Firebase Storage > String', () => { it('Encodes base64 strings without padding correctly', () => { const str = 'CpYlM1+XsGxTd1n6izHMU/yY3Bw'; const base64Bytes = new Uint8Array([ - 0x0a, - 0x96, - 0x25, - 0x33, - 0x5f, - 0x97, - 0xb0, - 0x6c, - 0x53, - 0x77, - 0x59, - 0xfa, - 0x8b, - 0x31, - 0xcc, - 0x53, - 0xfc, - 0x98, - 0xdc, - 0x1c + 0x0a, 0x96, 0x25, 0x33, 0x5f, 0x97, 0xb0, 0x6c, 0x53, 0x77, 0x59, 0xfa, + 0x8b, 0x31, 0xcc, 0x53, 0xfc, 0x98, 0xdc, 0x1c ]); assertUint8ArrayEquals( base64Bytes, @@ -155,26 +97,8 @@ describe('Firebase Storage > String', () => { it('Encodes base64url strings correctly', () => { const str = 'CpYlM1-XsGxTd1n6izHMU_yY3Bw='; const base64Bytes = new Uint8Array([ - 0x0a, - 0x96, - 0x25, - 0x33, - 0x5f, - 0x97, - 0xb0, - 0x6c, - 0x53, - 0x77, - 0x59, - 0xfa, - 0x8b, - 0x31, - 0xcc, - 0x53, - 0xfc, - 0x98, - 0xdc, - 0x1c + 0x0a, 0x96, 0x25, 0x33, 0x5f, 0x97, 0xb0, 0x6c, 0x53, 0x77, 0x59, 0xfa, + 0x8b, 0x31, 0xcc, 0x53, 0xfc, 0x98, 0xdc, 0x1c ]); assertUint8ArrayEquals( base64Bytes, @@ -184,26 +108,8 @@ describe('Firebase Storage > String', () => { it('Encodes base64url strings without padding correctly', () => { const str = 'CpYlM1-XsGxTd1n6izHMU_yY3Bw'; const base64Bytes = new Uint8Array([ - 0x0a, - 0x96, - 0x25, - 0x33, - 0x5f, - 0x97, - 0xb0, - 0x6c, - 0x53, - 0x77, - 0x59, - 0xfa, - 0x8b, - 0x31, - 0xcc, - 0x53, - 0xfc, - 0x98, - 0xdc, - 0x1c + 0x0a, 0x96, 0x25, 0x33, 0x5f, 0x97, 0xb0, 0x6c, 0x53, 0x77, 0x59, 0xfa, + 0x8b, 0x31, 0xcc, 0x53, 0xfc, 0x98, 0xdc, 0x1c ]); assertUint8ArrayEquals( base64Bytes, @@ -253,16 +159,7 @@ describe('Firebase Storage > String', () => { const data = dataFromString(StringFormat.DATA_URL, str); assertUint8ArrayEquals( new Uint8Array([ - 0xf0, - 0x9f, - 0x98, - 0x8a, - 0xe6, - 0x86, - 0x82, - 0xe9, - 0xac, - 0xb1 + 0xf0, 0x9f, 0x98, 0x8a, 0xe6, 0x86, 0x82, 0xe9, 0xac, 0xb1 ]), data.data ); diff --git a/packages/storage/test/unit/testshared.ts b/packages/storage/test/unit/testshared.ts index b0c368e87d4..835090d79af 100644 --- a/packages/storage/test/unit/testshared.ts +++ b/packages/storage/test/unit/testshared.ts @@ -152,10 +152,7 @@ export function bind(f: Function, ctx: any, ...args: any[]): () => void { }; } -export function assertThrows( - f: () => void, - code: string -): StorageError { +export function assertThrows(f: () => void, code: string): StorageError { let captured: StorageError | null = null; expect(() => { try {