From 0b091c9454adb56284cad04a75a03a06b0f46c91 Mon Sep 17 00:00:00 2001 From: Feiyang1 Date: Sat, 13 Mar 2021 22:11:21 -0800 Subject: [PATCH 01/11] Implement storage-compat --- packages/storage/compat-build/index.ts | 117 ++++++++++++++++++ packages/storage/compat/list.ts | 3 +- packages/storage/compat/reference.ts | 36 +++--- packages/storage/compat/service.ts | 9 +- packages/storage/compat/task.ts | 54 +++++--- packages/storage/compat/tasksnapshot.ts | 4 +- packages/storage/exp/index.ts | 15 ++- packages/storage/exp/public-types.ts | 5 +- packages/storage/src/implementation/blob.ts | 2 + .../storage/src/implementation/location.ts | 2 + packages/storage/src/reference.ts | 3 +- 11 files changed, 208 insertions(+), 42 deletions(-) create mode 100644 packages/storage/compat-build/index.ts diff --git a/packages/storage/compat-build/index.ts b/packages/storage/compat-build/index.ts new file mode 100644 index 00000000000..73bf6b19982 --- /dev/null +++ b/packages/storage/compat-build/index.ts @@ -0,0 +1,117 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import firebase from '@firebase/app'; +import { _FirebaseNamespace } from '@firebase/app-types/private'; +import { StringFormat } from '../exp/index'; + +import { ReferenceCompat } from '../compat/reference'; +import { StorageServiceCompat } from '../compat/service'; +import { TaskEvent, TaskState } from '../src/implementation/taskenums'; + +import * as types from '@firebase/storage-types'; +import { + Component, + ComponentType, + ComponentContainer, + InstanceFactoryOptions +} from '@firebase/component'; + +import { name, version } from '../package.json'; + +declare module '@firebase/component' { + interface NameServiceMapping { + 'storage-compat': types.FirebaseStorage; + } +} + +/** + * Type constant for Firebase Storage. + */ +const STORAGE_TYPE = 'storage-compat'; + +function factory( + container: ComponentContainer, + { instanceIdentifier: url }: InstanceFactoryOptions +): types.FirebaseStorage { + // Dependencies + // TODO: This should eventually be 'app-compat' + const app = container.getProvider('app').getImmediate(); + const storageExp = container.getProvider('storage-exp').getImmediate({ + identifier: url + }); + + // TODO: get StorageService instance from component framework instead + // of creating a new one. + const storageServiceCompat: StorageServiceCompat = new StorageServiceCompat( + app, + storageExp + ); + return storageServiceCompat; +} + +export function registerStorage(instance: _FirebaseNamespace): void { + const namespaceExports = { + // no-inline + TaskState, + TaskEvent, + StringFormat, + Storage: StorageServiceCompat, + Reference: ReferenceCompat + }; + instance.INTERNAL.registerComponent( + new Component(STORAGE_TYPE, factory, ComponentType.PUBLIC) + .setServiceProps(namespaceExports) + .setMultipleInstances(true) + ); + + instance.registerVersion(name, version); +} + +registerStorage(firebase as _FirebaseNamespace); + +/** + * Define extension behavior for `registerStorage` + */ +declare module '@firebase/app-types' { + interface FirebaseNamespace { + storage?: { + (app?: FirebaseApp, url?: string): types.FirebaseStorage; + Storage: typeof types.FirebaseStorage; + + StringFormat: { + BASE64: types.StringFormat; + BASE64URL: types.StringFormat; + DATA_URL: types.StringFormat; + RAW: types.StringFormat; + }; + TaskEvent: { + STATE_CHANGED: types.TaskEvent; + }; + TaskState: { + CANCELED: types.TaskState; + ERROR: types.TaskState; + PAUSED: types.TaskState; + RUNNING: types.TaskState; + SUCCESS: types.TaskState; + }; + }; + } + interface FirebaseApp { + storage?(storageBucket?: string): types.FirebaseStorage; + } +} diff --git a/packages/storage/compat/list.ts b/packages/storage/compat/list.ts index 46553b924f0..42df617fa31 100644 --- a/packages/storage/compat/list.ts +++ b/packages/storage/compat/list.ts @@ -14,9 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +import { ListResult } from '../exp/index'; import * as types from '@firebase/storage-types'; -import { ListResult } from '../src/list'; import { ReferenceCompat } from './reference'; import { StorageServiceCompat } from './service'; diff --git a/packages/storage/compat/reference.ts b/packages/storage/compat/reference.ts index b18e5af4f02..d0bae69929a 100644 --- a/packages/storage/compat/reference.ts +++ b/packages/storage/compat/reference.ts @@ -16,29 +16,33 @@ */ import { - Reference, - _getChild, + StorageReference, uploadBytesResumable, list, listAll, getDownloadURL, getMetadata, updateMetadata, - deleteObject -} from '../src/reference'; -import * as types from '@firebase/storage-types'; -import { Metadata } from '../src/metadata'; -import { dataFromString, StringFormat } from '../src/implementation/string'; + deleteObject, + UploadTask, + StringFormat, + _UploadTask, + _getChild, + _Reference, + _FbsBlob +} from '../exp/index'; // import from the exp public API import { UploadTaskCompat } from './task'; import { ListResultCompat } from './list'; import { StorageServiceCompat } from './service'; + +import * as types from '@firebase/storage-types'; +import { Metadata } from '../src/metadata'; +import { dataFromString } from '../src/implementation/string'; import { invalidRootOperation } from '../src/implementation/error'; -import { UploadTask } from '../src/task'; -import { FbsBlob } from '../src/implementation/blob'; export class ReferenceCompat implements types.Reference { constructor( - private readonly _delegate: Reference, + private readonly _delegate: StorageReference, public storage: StorageServiceCompat ) {} @@ -120,11 +124,11 @@ export class ReferenceCompat implements types.Reference { metadataClone['contentType'] = data.contentType; } return new UploadTaskCompat( - new UploadTask( - this._delegate, - new FbsBlob(data.data, true), + new _UploadTask( + this._delegate as _Reference, + new _FbsBlob(data.data, true), metadataClone - ), + ) as UploadTask, this ); } @@ -172,7 +176,7 @@ export class ReferenceCompat implements types.Reference { * can be used to get the rest of the results. */ list(options?: types.ListOptions | null): Promise { - return list(this._delegate, options).then( + return list(this._delegate, options || undefined).then( r => new ListResultCompat(r, this.storage) ); } @@ -222,7 +226,7 @@ export class ReferenceCompat implements types.Reference { } private _throwIfRoot(name: string): void { - if (this._delegate._location.path === '') { + if ((this._delegate as _Reference)._location.path === '') { throw invalidRootOperation(name); } } diff --git a/packages/storage/compat/service.ts b/packages/storage/compat/service.ts index e6159855d45..3dcf4a03d0c 100644 --- a/packages/storage/compat/service.ts +++ b/packages/storage/compat/service.ts @@ -16,11 +16,12 @@ */ import * as types from '@firebase/storage-types'; -import { StorageService, isUrl, ref } from '../src/service'; -import { Location } from '../src/implementation/location'; +import { FirebaseApp } from '@firebase/app-types'; + +import { StorageService, ref, _Location } from '../exp/index'; // import from the exp public API import { ReferenceCompat } from './reference'; +import { isUrl } from '../src/service'; import { invalidArgument } from '../src/implementation/error'; -import { FirebaseApp } from '@firebase/app-types'; /** * A service that provides firebaseStorage.Reference instances. @@ -70,7 +71,7 @@ export class StorageServiceCompat implements types.FirebaseStorage { ); } try { - Location.makeFromUrl(url); + _Location.makeFromUrl(url); } catch (e) { throw invalidArgument( 'refFromUrl() expected a valid full URL but got an invalid one.' diff --git a/packages/storage/compat/task.ts b/packages/storage/compat/task.ts index e9791816c64..a4b2bfb6e70 100644 --- a/packages/storage/compat/task.ts +++ b/packages/storage/compat/task.ts @@ -15,20 +15,16 @@ * limitations under the License. */ -import { UploadTask } from '../src/task'; -import { UploadTaskSnapshotCompat } from './tasksnapshot'; -import { TaskEvent } from '../src/implementation/taskenums'; -import * as types from '@firebase/storage-types'; import { - StorageObserver, - ErrorFn, - CompleteFn, - Subscribe, - Unsubscribe -} from '../src/implementation/observer'; -import { UploadTaskSnapshot } from '../src/tasksnapshot'; + UploadTask, + FirebaseStorageError, + UploadTaskSnapshot, + TaskEvent, + StorageObserver +} from '../exp/index'; +import { UploadTaskSnapshotCompat } from './tasksnapshot'; import { ReferenceCompat } from './reference'; -import { FirebaseStorageError } from '../src/implementation/error'; +import * as types from '@firebase/storage-types'; export class UploadTaskCompat implements types.UploadTask { constructor( @@ -68,8 +64,8 @@ export class UploadTaskCompat implements types.UploadTask { | types.StorageObserver | null | ((a: UploadTaskSnapshotCompat) => unknown), - error?: ErrorFn | null, - completed?: CompleteFn | null + error?: (error: FirebaseStorageError) => void | null, + completed?: () => void | null ): Unsubscribe | Subscribe { let wrappedNextOrObserver: | StorageObserver @@ -102,3 +98,33 @@ export class UploadTaskCompat implements types.UploadTask { ); } } + +/** + * Subscribes to an event stream. + */ +export type Subscribe = ( + next?: NextFn | StorageObserver, + error?: ErrorFn, + complete?: CompleteFn +) => Unsubscribe; + +/** + * Unsubscribes from a stream. + */ +export type Unsubscribe = () => void; + +/** + * Function that is called once for each value in a stream of values. + */ +export type NextFn = (value: T) => void; + +/** + * A function that is called with a `FirebaseStorageError` + * if the event stream ends due to an error. + */ +export type ErrorFn = (error: FirebaseStorageError) => void; + +/** + * A function that is called if the event stream ends normally. + */ +export type CompleteFn = () => void; diff --git a/packages/storage/compat/tasksnapshot.ts b/packages/storage/compat/tasksnapshot.ts index 6558db4306b..5c23d61ba00 100644 --- a/packages/storage/compat/tasksnapshot.ts +++ b/packages/storage/compat/tasksnapshot.ts @@ -15,10 +15,10 @@ * limitations under the License. */ -import * as types from '@firebase/storage-types'; +import { UploadTaskSnapshot } from '../exp/index'; import { ReferenceCompat } from './reference'; import { UploadTaskCompat } from './task'; -import { UploadTaskSnapshot } from '../src/tasksnapshot'; +import * as types from '@firebase/storage-types'; export class UploadTaskSnapshotCompat implements types.UploadTaskSnapshot { constructor( diff --git a/packages/storage/exp/index.ts b/packages/storage/exp/index.ts index a78b4b969c6..b6ec2c7b8bc 100644 --- a/packages/storage/exp/index.ts +++ b/packages/storage/exp/index.ts @@ -61,7 +61,8 @@ import { listAll as listAllInternal, getDownloadURL as getDownloadURLInternal, deleteObject as deleteObjectInternal, - Reference + Reference, + _getChild as _getChildInternal } from '../src/reference'; /** @@ -69,6 +70,11 @@ import { */ export * from './public-types'; +export { Location as _Location } from '../src/implementation/location'; +export { UploadTask as _UploadTask } from '../src/task'; +export type { Reference as _Reference } from '../src/reference'; +export { FbsBlob as _FbsBlob } from '../src/implementation/blob'; + /** * Uploads data to this object's location. * The upload is not resumable. @@ -266,6 +272,13 @@ export function ref( ); } +/** + * @internal + */ +export function _getChild(ref: StorageReference, childPath: string): Reference { + return _getChildInternal(ref as Reference, childPath); +} + export { StringFormat } from '../src/implementation/string'; /** diff --git a/packages/storage/exp/public-types.ts b/packages/storage/exp/public-types.ts index 842d04daaf0..aaaca1f0625 100644 --- a/packages/storage/exp/public-types.ts +++ b/packages/storage/exp/public-types.ts @@ -16,7 +16,7 @@ */ // eslint-disable-next-line import/no-extraneous-dependencies -import { FirebaseApp } from '@firebase/app-exp'; +import { FirebaseApp, _FirebaseService } from '@firebase/app-exp'; import { CompleteFn, FirebaseError, @@ -29,11 +29,12 @@ import { * A Firebase Storage instance. * @public */ -export interface StorageService { +export interface StorageService extends _FirebaseService { /** * FirebaseApp associated with this StorageService instance. */ readonly app: FirebaseApp; + /** * The maximum time to retry uploads in milliseconds. */ diff --git a/packages/storage/src/implementation/blob.ts b/packages/storage/src/implementation/blob.ts index 0794efd4109..85ee0e84ee4 100644 --- a/packages/storage/src/implementation/blob.ts +++ b/packages/storage/src/implementation/blob.ts @@ -28,6 +28,8 @@ import { isNativeBlob, isNativeBlobDefined, isString } from './type'; * @param opt_elideCopy - If true, doesn't copy mutable input data * (e.g. Uint8Arrays). Pass true only if you know the objects will not be * modified after this blob's construction. + * + * @internal */ export class FbsBlob { private data_!: Blob | Uint8Array; diff --git a/packages/storage/src/implementation/location.ts b/packages/storage/src/implementation/location.ts index 229b29d3eba..649203b7a32 100644 --- a/packages/storage/src/implementation/location.ts +++ b/packages/storage/src/implementation/location.ts @@ -25,6 +25,8 @@ import { DEFAULT_HOST } from './constants'; /** * Firebase Storage location data. + * + * @internal */ export class Location { private path_: string; diff --git a/packages/storage/src/reference.ts b/packages/storage/src/reference.ts index 7751e4f405b..db08e704c42 100644 --- a/packages/storage/src/reference.ts +++ b/packages/storage/src/reference.ts @@ -43,7 +43,7 @@ import { UploadResult } from './tasksnapshot'; /** * Provides methods to interact with a bucket in the Firebase Storage service. - * @public + * @internal * @param _location - An fbs.location, or the URL at * which to base this object, in one of the following forms: * gs:/// @@ -404,6 +404,7 @@ export async function deleteObject(ref: Reference): Promise { * @returns A reference to the object obtained by * appending childPath, removing any duplicate, beginning, or trailing * slashes. + * */ export function _getChild(ref: Reference, childPath: string): Reference { const newPath = child(ref._location.path, childPath); From 4cb92336f5060a3fe878b1564b7bf8d7a00aa516 Mon Sep 17 00:00:00 2001 From: Feiyang1 Date: Sat, 13 Mar 2021 22:33:38 -0800 Subject: [PATCH 02/11] save --- packages/storage/compat/package.json | 13 +++ packages/storage/index.ts | 116 +++++++++++++++++++++++++++ packages/storage/package.json | 2 +- packages/storage/rollup.config.js | 77 ++++++++++++++++++ 4 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 packages/storage/compat/package.json create mode 100644 packages/storage/index.ts create mode 100644 packages/storage/rollup.config.js diff --git a/packages/storage/compat/package.json b/packages/storage/compat/package.json new file mode 100644 index 00000000000..c51e9d6769c --- /dev/null +++ b/packages/storage/compat/package.json @@ -0,0 +1,13 @@ +{ + "name": "@firebase/storage-compat", + "version": "0.0.900", + "description": "The Cloud Storage component of the Firebase JS SDK.", + "author": "Firebase (https://firebase.google.com/)", + "main": "../dist/compat/node-cjs/index.js", + "browser": "../dist/compat/esm5/index.js", + "module": "../dist/compat/esm5/index.js", + "esm2017": "../dist/compat/esm2017/index.js", + "license": "Apache-2.0", + "typings": "../dist/compat/esm5/packages/firestore/compat/index.d.ts" + } + \ No newline at end of file diff --git a/packages/storage/index.ts b/packages/storage/index.ts new file mode 100644 index 00000000000..5d1596c75be --- /dev/null +++ b/packages/storage/index.ts @@ -0,0 +1,116 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import firebase from '@firebase/app'; +import { _FirebaseNamespace } from '@firebase/app-types/private'; +import { StringFormat } from './src/implementation/string'; +import { TaskEvent, TaskState } from './src/implementation/taskenums'; + +import { XhrIoPool } from './src/implementation/xhriopool'; +import { ReferenceCompat } from './compat/reference'; +import { StorageServiceCompat } from './compat/service'; +import { StorageService } from './src/service'; +import * as types from '@firebase/storage-types'; +import { + Component, + ComponentType, + ComponentContainer, + InstanceFactoryOptions +} from '@firebase/component'; + +import { name, version } from './package.json'; + +/** + * Type constant for Firebase Storage. + */ +const STORAGE_TYPE = 'storage'; + +function factory( + container: ComponentContainer, + { instanceIdentifier: url }: InstanceFactoryOptions +): types.FirebaseStorage { + // Dependencies + // TODO: This should eventually be 'app-compat' + const app = container.getProvider('app').getImmediate(); + const authProvider = container.getProvider('auth-internal'); + + // TODO: get StorageService instance from component framework instead + // of creating a new one. + const storageServiceCompat: StorageServiceCompat = new StorageServiceCompat( + app, + new StorageService( + app, + authProvider, + new XhrIoPool(), + url, + firebase.SDK_VERSION + ) + ); + return storageServiceCompat; +} + +export function registerStorage(instance: _FirebaseNamespace): void { + const namespaceExports = { + // no-inline + TaskState, + TaskEvent, + StringFormat, + Storage: StorageService, + Reference: ReferenceCompat + }; + instance.INTERNAL.registerComponent( + new Component(STORAGE_TYPE, factory, ComponentType.PUBLIC) + .setServiceProps(namespaceExports) + .setMultipleInstances(true) + ); + + instance.registerVersion(name, version); +} + +registerStorage(firebase as _FirebaseNamespace); + +/** + * Define extension behavior for `registerStorage` + */ +declare module '@firebase/app-types' { + interface FirebaseNamespace { + storage?: { + (app?: FirebaseApp, url?: string): types.FirebaseStorage; + Storage: typeof types.FirebaseStorage; + + StringFormat: { + BASE64: types.StringFormat; + BASE64URL: types.StringFormat; + DATA_URL: types.StringFormat; + RAW: types.StringFormat; + }; + TaskEvent: { + STATE_CHANGED: types.TaskEvent; + }; + TaskState: { + CANCELED: types.TaskState; + ERROR: types.TaskState; + PAUSED: types.TaskState; + RUNNING: types.TaskState; + SUCCESS: types.TaskState; + }; + }; + } + interface FirebaseApp { + storage?(storageBucket?: string): types.FirebaseStorage; + } +} diff --git a/packages/storage/package.json b/packages/storage/package.json index 45440e731bb..86061417083 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -14,7 +14,7 @@ "scripts": { "lint": "eslint -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'", "lint:fix": "eslint --fix -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'", - "build": "rollup -c rollup.config.compat.js && yarn build:exp", + "build": "rollup -c rollup.config.js && yarn build:exp", "build:exp": "rollup -c rollup.config.exp.js ; yarn api-report", "build:deps": "lerna run --scope @firebase/storage --include-dependencies build", "dev": "rollup -c -w", diff --git a/packages/storage/rollup.config.js b/packages/storage/rollup.config.js new file mode 100644 index 00000000000..e78b01ca5b2 --- /dev/null +++ b/packages/storage/rollup.config.js @@ -0,0 +1,77 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import json from '@rollup/plugin-json'; +import typescriptPlugin from 'rollup-plugin-typescript2'; +import typescript from 'typescript'; +import pkg from './package.json'; + +const deps = Object.keys( + Object.assign({}, pkg.peerDependencies, pkg.dependencies) +); +/** + * ES5 Builds + */ +const es5BuildPlugins = [ + typescriptPlugin({ + typescript + }), + json() +]; + +const es5Builds = [ + { + input: './index.ts', + output: [ + { file: pkg.main, format: 'cjs', sourcemap: true }, + { file: pkg.module, format: 'es', sourcemap: true } + ], + plugins: es5BuildPlugins, + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + } +]; + +/** + * ES2017 Builds + */ +const es2017BuildPlugins = [ + typescriptPlugin({ + typescript, + tsconfigOverride: { + compilerOptions: { + target: 'es2017' + } + } + }), + json({ preferConst: true }) +]; + +const es2017Builds = [ + { + input: './index.ts', + output: { + file: pkg.esm2017, + format: 'es', + sourcemap: true + }, + plugins: es2017BuildPlugins, + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + } +]; + +// eslint-disable-next-line import/no-default-export +export default [...es5Builds, ...es2017Builds]; From e34c9bc5767d54933c70d98d0354ee9183129b55 Mon Sep 17 00:00:00 2001 From: Feiyang1 Date: Sat, 13 Mar 2021 22:50:29 -0800 Subject: [PATCH 03/11] build storage compat --- packages/storage/compat-build/index.ts | 117 ----------------------- packages/storage/compat/index.ts | 4 +- packages/storage/compat/reference.ts | 1 + packages/storage/package.json | 1 + packages/storage/rollup.config.compat.js | 41 ++++++-- 5 files changed, 38 insertions(+), 126 deletions(-) delete mode 100644 packages/storage/compat-build/index.ts diff --git a/packages/storage/compat-build/index.ts b/packages/storage/compat-build/index.ts deleted file mode 100644 index 73bf6b19982..00000000000 --- a/packages/storage/compat-build/index.ts +++ /dev/null @@ -1,117 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import firebase from '@firebase/app'; -import { _FirebaseNamespace } from '@firebase/app-types/private'; -import { StringFormat } from '../exp/index'; - -import { ReferenceCompat } from '../compat/reference'; -import { StorageServiceCompat } from '../compat/service'; -import { TaskEvent, TaskState } from '../src/implementation/taskenums'; - -import * as types from '@firebase/storage-types'; -import { - Component, - ComponentType, - ComponentContainer, - InstanceFactoryOptions -} from '@firebase/component'; - -import { name, version } from '../package.json'; - -declare module '@firebase/component' { - interface NameServiceMapping { - 'storage-compat': types.FirebaseStorage; - } -} - -/** - * Type constant for Firebase Storage. - */ -const STORAGE_TYPE = 'storage-compat'; - -function factory( - container: ComponentContainer, - { instanceIdentifier: url }: InstanceFactoryOptions -): types.FirebaseStorage { - // Dependencies - // TODO: This should eventually be 'app-compat' - const app = container.getProvider('app').getImmediate(); - const storageExp = container.getProvider('storage-exp').getImmediate({ - identifier: url - }); - - // TODO: get StorageService instance from component framework instead - // of creating a new one. - const storageServiceCompat: StorageServiceCompat = new StorageServiceCompat( - app, - storageExp - ); - return storageServiceCompat; -} - -export function registerStorage(instance: _FirebaseNamespace): void { - const namespaceExports = { - // no-inline - TaskState, - TaskEvent, - StringFormat, - Storage: StorageServiceCompat, - Reference: ReferenceCompat - }; - instance.INTERNAL.registerComponent( - new Component(STORAGE_TYPE, factory, ComponentType.PUBLIC) - .setServiceProps(namespaceExports) - .setMultipleInstances(true) - ); - - instance.registerVersion(name, version); -} - -registerStorage(firebase as _FirebaseNamespace); - -/** - * Define extension behavior for `registerStorage` - */ -declare module '@firebase/app-types' { - interface FirebaseNamespace { - storage?: { - (app?: FirebaseApp, url?: string): types.FirebaseStorage; - Storage: typeof types.FirebaseStorage; - - StringFormat: { - BASE64: types.StringFormat; - BASE64URL: types.StringFormat; - DATA_URL: types.StringFormat; - RAW: types.StringFormat; - }; - TaskEvent: { - STATE_CHANGED: types.TaskEvent; - }; - TaskState: { - CANCELED: types.TaskState; - ERROR: types.TaskState; - PAUSED: types.TaskState; - RUNNING: types.TaskState; - SUCCESS: types.TaskState; - }; - }; - } - interface FirebaseApp { - storage?(storageBucket?: string): types.FirebaseStorage; - } -} diff --git a/packages/storage/compat/index.ts b/packages/storage/compat/index.ts index 2b177bf7f92..9239b3ca46e 100644 --- a/packages/storage/compat/index.ts +++ b/packages/storage/compat/index.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import firebase from '@firebase/app'; +import firebase from '@firebase/app-compat'; import { _FirebaseNamespace } from '@firebase/app-types/private'; import { StringFormat } from '../src/implementation/string'; import { TaskEvent, TaskState } from '../src/implementation/taskenums'; @@ -81,7 +81,7 @@ export function registerStorage(instance: _FirebaseNamespace): void { instance.registerVersion(name, version); } -registerStorage(firebase as _FirebaseNamespace); +registerStorage((firebase as unknown) as _FirebaseNamespace); /** * Define extension behavior for `registerStorage` diff --git a/packages/storage/compat/reference.ts b/packages/storage/compat/reference.ts index d0bae69929a..5c92824b5ec 100644 --- a/packages/storage/compat/reference.ts +++ b/packages/storage/compat/reference.ts @@ -31,6 +31,7 @@ import { _Reference, _FbsBlob } from '../exp/index'; // import from the exp public API + import { UploadTaskCompat } from './task'; import { ListResultCompat } from './list'; import { StorageServiceCompat } from './service'; diff --git a/packages/storage/package.json b/packages/storage/package.json index 86061417083..b13f5749958 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -16,6 +16,7 @@ "lint:fix": "eslint --fix -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'", "build": "rollup -c rollup.config.js && yarn build:exp", "build:exp": "rollup -c rollup.config.exp.js ; yarn api-report", + "build:compat": "rollup -c rollup.config.compat.js", "build:deps": "lerna run --scope @firebase/storage --include-dependencies build", "dev": "rollup -c -w", "test": "run-p test:browser lint", diff --git a/packages/storage/rollup.config.compat.js b/packages/storage/rollup.config.compat.js index 3b2bb2102b8..2d154adc969 100644 --- a/packages/storage/rollup.config.compat.js +++ b/packages/storage/rollup.config.compat.js @@ -20,15 +20,26 @@ import typescriptPlugin from 'rollup-plugin-typescript2'; import typescript from 'typescript'; import pkg from './package.json'; -const deps = Object.keys( - Object.assign({}, pkg.peerDependencies, pkg.dependencies) -); +import { getImportPathTransformer } from '../../scripts/exp/ts-transform-import-path'; + +const deps = [ + ...Object.keys(Object.assign({}, pkg.peerDependencies, pkg.dependencies)), + '@firebase/storage' +]; /** * ES5 Builds */ const es5BuildPlugins = [ typescriptPlugin({ - typescript + typescript, + abortOnError: false, + transformers: [ + getImportPathTransformer({ + // ../exp/index + pattern: /^.*exp\/index$/g, + template: ['@firebase/storage'] + }) + ] }), json() ]; @@ -37,8 +48,16 @@ const es5Builds = [ { input: './compat/index.ts', output: [ - { file: pkg.main, format: 'cjs', sourcemap: true }, - { file: pkg.module, format: 'es', sourcemap: true } + { + dir: 'dist/compat/cjs', + format: 'cjs', + sourcemap: true + }, + { + dir: 'dist/compat/esm5', + format: 'es', + sourcemap: true + } ], plugins: es5BuildPlugins, external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) @@ -51,6 +70,14 @@ const es5Builds = [ const es2017BuildPlugins = [ typescriptPlugin({ typescript, + abortOnError: false, + transformers: [ + getImportPathTransformer({ + // ../exp/index + pattern: /^.*exp\/index$/g, + template: ['@firebase/storage'] + }) + ], tsconfigOverride: { compilerOptions: { target: 'es2017' @@ -64,7 +91,7 @@ const es2017Builds = [ { input: './compat/index.ts', output: { - file: pkg.esm2017, + dir: 'dist/compat/esm2017', format: 'es', sourcemap: true }, From 38eee09c5dab962ed80031212ff1e1095e06bc79 Mon Sep 17 00:00:00 2001 From: Feiyang1 Date: Sun, 14 Mar 2021 23:03:57 -0700 Subject: [PATCH 04/11] build v8 correctly --- packages/storage/compat/list.ts | 2 +- packages/storage/compat/reference.ts | 2 +- packages/storage/compat/service.ts | 2 +- packages/storage/compat/task.ts | 2 +- packages/storage/compat/tasksnapshot.ts | 2 +- packages/storage/exp/api.ts | 295 +++++++++++++++++++++++ packages/storage/exp/constants.ts | 21 ++ packages/storage/exp/index.ts | 280 +-------------------- packages/storage/rollup.config.compat.js | 4 +- packages/storage/rollup.config.js | 10 +- 10 files changed, 336 insertions(+), 284 deletions(-) create mode 100644 packages/storage/exp/api.ts create mode 100644 packages/storage/exp/constants.ts diff --git a/packages/storage/compat/list.ts b/packages/storage/compat/list.ts index 42df617fa31..805749a4eba 100644 --- a/packages/storage/compat/list.ts +++ b/packages/storage/compat/list.ts @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { ListResult } from '../exp/index'; +import { ListResult } from '../exp/api'; import * as types from '@firebase/storage-types'; import { ReferenceCompat } from './reference'; import { StorageServiceCompat } from './service'; diff --git a/packages/storage/compat/reference.ts b/packages/storage/compat/reference.ts index 5c92824b5ec..f91e38f470e 100644 --- a/packages/storage/compat/reference.ts +++ b/packages/storage/compat/reference.ts @@ -30,7 +30,7 @@ import { _getChild, _Reference, _FbsBlob -} from '../exp/index'; // import from the exp public API +} from '../exp/api'; // import from the exp public API import { UploadTaskCompat } from './task'; import { ListResultCompat } from './list'; diff --git a/packages/storage/compat/service.ts b/packages/storage/compat/service.ts index 3dcf4a03d0c..25a1890bdd8 100644 --- a/packages/storage/compat/service.ts +++ b/packages/storage/compat/service.ts @@ -18,7 +18,7 @@ import * as types from '@firebase/storage-types'; import { FirebaseApp } from '@firebase/app-types'; -import { StorageService, ref, _Location } from '../exp/index'; // import from the exp public API +import { StorageService, ref, _Location } from '../exp/api'; // import from the exp public API import { ReferenceCompat } from './reference'; import { isUrl } from '../src/service'; import { invalidArgument } from '../src/implementation/error'; diff --git a/packages/storage/compat/task.ts b/packages/storage/compat/task.ts index a4b2bfb6e70..10637782af4 100644 --- a/packages/storage/compat/task.ts +++ b/packages/storage/compat/task.ts @@ -21,7 +21,7 @@ import { UploadTaskSnapshot, TaskEvent, StorageObserver -} from '../exp/index'; +} from '../exp/api'; import { UploadTaskSnapshotCompat } from './tasksnapshot'; import { ReferenceCompat } from './reference'; import * as types from '@firebase/storage-types'; diff --git a/packages/storage/compat/tasksnapshot.ts b/packages/storage/compat/tasksnapshot.ts index 5c23d61ba00..71d3584da81 100644 --- a/packages/storage/compat/tasksnapshot.ts +++ b/packages/storage/compat/tasksnapshot.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { UploadTaskSnapshot } from '../exp/index'; +import { UploadTaskSnapshot } from '../exp/api'; import { ReferenceCompat } from './reference'; import { UploadTaskCompat } from './task'; import * as types from '@firebase/storage-types'; diff --git a/packages/storage/exp/api.ts b/packages/storage/exp/api.ts new file mode 100644 index 00000000000..e3448306ff7 --- /dev/null +++ b/packages/storage/exp/api.ts @@ -0,0 +1,295 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + _registerComponent, + _getProvider, + FirebaseApp + // eslint-disable-next-line import/no-extraneous-dependencies +} from '@firebase/app-exp'; + +import { + ref as refInternal, + StorageService as StorageServiceInternal +} from '../src/service'; +import { Provider } from '@firebase/component'; + +import { + StorageReference, + StorageService, + UploadResult, + ListOptions, + ListResult, + UploadTask, + SettableMetadata, + UploadMetadata, + FullMetadata +} from './public-types'; +import { Metadata as MetadataInternal } from '../src/metadata'; +import { + uploadBytes as uploadBytesInternal, + uploadBytesResumable as uploadBytesResumableInternal, + uploadString as uploadStringInternal, + getMetadata as getMetadataInternal, + updateMetadata as updateMetadataInternal, + list as listInternal, + listAll as listAllInternal, + getDownloadURL as getDownloadURLInternal, + deleteObject as deleteObjectInternal, + Reference, + _getChild as _getChildInternal +} from '../src/reference'; +import { STORAGE_TYPE } from './constants'; + +/** + * Public types. + */ +export * from './public-types'; + +export { Location as _Location } from '../src/implementation/location'; +export { UploadTask as _UploadTask } from '../src/task'; +export type { Reference as _Reference } from '../src/reference'; +export { FbsBlob as _FbsBlob } from '../src/implementation/blob'; + +/** + * Uploads data to this object's location. + * The upload is not resumable. + * @public + * @param ref - StorageReference where data should be uploaded. + * @param data - The data to upload. + * @param metadata - Metadata for the data to upload. + * @returns A Promise containing an UploadResult + */ +export function uploadBytes( + ref: StorageReference, + data: Blob | Uint8Array | ArrayBuffer, + metadata?: UploadMetadata +): Promise { + return uploadBytesInternal( + ref as Reference, + data, + metadata as MetadataInternal + ); +} + +/** + * Uploads a string to this object's location. + * The upload is not resumable. + * @public + * @param ref - StorageReference where string should be uploaded. + * @param value - The string to upload. + * @param format - The format of the string to upload. + * @param metadata - Metadata for the string to upload. + * @returns A Promise containing an UploadResult + */ +export function uploadString( + ref: StorageReference, + value: string, + format?: string, + metadata?: UploadMetadata +): Promise { + return uploadStringInternal( + ref as Reference, + value, + format, + metadata as MetadataInternal + ); +} + +/** + * Uploads data to this object's location. + * The upload can be paused and resumed, and exposes progress updates. + * @public + * @param ref - StorageReference where data should be uploaded. + * @param data - The data to upload. + * @param metadata - Metadata for the data to upload. + * @returns An UploadTask + */ +export function uploadBytesResumable( + ref: StorageReference, + data: Blob | Uint8Array | ArrayBuffer, + metadata?: UploadMetadata +): UploadTask { + return uploadBytesResumableInternal( + ref as Reference, + data, + metadata as MetadataInternal + ) as UploadTask; +} + +/** + * A promise that resolves with the metadata for this object. If this + * object doesn't exist or metadata cannot be retreived, the promise is + * rejected. + * @public + * @param ref - StorageReference to get metadata from. + */ +export function getMetadata(ref: StorageReference): Promise { + return getMetadataInternal(ref as Reference) as Promise; +} + +/** + * Updates the metadata for this object. + * @public + * @param ref - StorageReference to update metadata for. + * @param metadata - The new metadata for the object. + * Only values that have been explicitly set will be changed. Explicitly + * setting a value to null will remove the metadata. + * @returns A promise that resolves with the new metadata for this object. + */ +export function updateMetadata( + ref: StorageReference, + metadata: SettableMetadata +): Promise { + return updateMetadataInternal( + ref as Reference, + metadata as Partial + ) as Promise; +} + +/** + * List items (files) and prefixes (folders) under this storage reference. + * + * List API is only available for Firebase Rules Version 2. + * + * GCS is a key-blob store. Firebase Storage imposes the semantic of '/' + * delimited folder structure. + * Refer to GCS's List API if you want to learn more. + * + * To adhere to Firebase Rules's Semantics, Firebase Storage does not + * support objects whose paths end with "/" or contain two consecutive + * "/"s. Firebase Storage List API will filter these unsupported objects. + * list() may fail if there are too many unsupported objects in the bucket. + * @public + * + * @param ref - StorageReference to get list from. + * @param options - See ListOptions for details. + * @returns A Promise that resolves with the items and prefixes. + * `prefixes` contains references to sub-folders and `items` + * contains references to objects in this folder. `nextPageToken` + * can be used to get the rest of the results. + */ +export function list( + ref: StorageReference, + options?: ListOptions +): Promise { + return listInternal(ref as Reference, options); +} + +/** + * List all items (files) and prefixes (folders) under this storage reference. + * + * This is a helper method for calling list() repeatedly until there are + * no more results. The default pagination size is 1000. + * + * Note: The results may not be consistent if objects are changed while this + * operation is running. + * + * Warning: listAll may potentially consume too many resources if there are + * too many results. + * @public + * @param ref - StorageReference to get list from. + * + * @returns A Promise that resolves with all the items and prefixes under + * the current storage reference. `prefixes` contains references to + * sub-directories and `items` contains references to objects in this + * folder. `nextPageToken` is never returned. + */ +export function listAll(ref: StorageReference): Promise { + return listAllInternal(ref as Reference); +} + +/** + * Returns the download URL for the given Reference. + * @public + * @returns A promise that resolves with the download + * URL for this object. + */ +export function getDownloadURL(ref: StorageReference): Promise { + return getDownloadURLInternal(ref as Reference); +} + +/** + * Deletes the object at this location. + * @public + * @param ref - StorageReference for object to delete. + * @returns A promise that resolves if the deletion succeeds. + */ +export function deleteObject(ref: StorageReference): Promise { + return deleteObjectInternal(ref as Reference); +} + +/** + * Returns a StorageReference for the given url. + * @param storage - `StorageService` instance. + * @param url - URL. If empty, returns root reference. + * @public + */ +export function ref(storage: StorageService, url?: string): StorageReference; +/** + * Returns a StorageReference for the given path in the + * default bucket. + * @param storageOrRef - `StorageService` or `StorageReference`. + * @param pathOrUrlStorage - path. If empty, returns root reference (if Storage + * instance provided) or returns same reference (if Reference provided). + * @public + */ +export function ref( + storageOrRef: StorageService | StorageReference, + path?: string +): StorageReference; +export function ref( + serviceOrRef: StorageService | StorageReference, + pathOrUrl?: string +): StorageReference | null { + return refInternal( + serviceOrRef as StorageServiceInternal | Reference, + pathOrUrl + ); +} + +/** + * @internal + */ +export function _getChild(ref: StorageReference, childPath: string): Reference { + return _getChildInternal(ref as Reference, childPath); +} + +export { StringFormat } from '../src/implementation/string'; + +/** + * Gets a Firebase StorageService instance for the given Firebase app. + * @public + * @param app - Firebase app to get Storage instance for. + * @param bucketUrl - The gs:// url to your Firebase Storage Bucket. + * If not passed, uses the app's default Storage Bucket. + * @returns A Firebase StorageService instance. + */ +export function getStorage( + app: FirebaseApp, + bucketUrl?: string +): StorageService { + // Dependencies + const storageProvider: Provider<'storage-exp'> = _getProvider( + app, + STORAGE_TYPE + ); + const storageInstance = storageProvider.getImmediate({ + identifier: bucketUrl + }); + return storageInstance; +} diff --git a/packages/storage/exp/constants.ts b/packages/storage/exp/constants.ts new file mode 100644 index 00000000000..a14f489490e --- /dev/null +++ b/packages/storage/exp/constants.ts @@ -0,0 +1,21 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Type constant for Firebase Storage. + */ +export const STORAGE_TYPE = 'storage-exp'; diff --git a/packages/storage/exp/index.ts b/packages/storage/exp/index.ts index b6ec2c7b8bc..6c33e2b854d 100644 --- a/packages/storage/exp/index.ts +++ b/packages/storage/exp/index.ts @@ -19,295 +19,25 @@ import { _registerComponent, registerVersion, _getProvider, - SDK_VERSION, - FirebaseApp + SDK_VERSION // eslint-disable-next-line import/no-extraneous-dependencies } from '@firebase/app-exp'; import { XhrIoPool } from '../src/implementation/xhriopool'; -import { - ref as refInternal, - StorageService as StorageServiceInternal -} from '../src/service'; +import { StorageService as StorageServiceInternal } from '../src/service'; import { Component, ComponentType, ComponentContainer, - Provider, InstanceFactoryOptions } from '@firebase/component'; import { name, version } from '../package.json'; -import { - StorageReference, - StorageService, - UploadResult, - ListOptions, - ListResult, - UploadTask, - SettableMetadata, - UploadMetadata, - FullMetadata -} from './public-types'; -import { Metadata as MetadataInternal } from '../src/metadata'; -import { - uploadBytes as uploadBytesInternal, - uploadBytesResumable as uploadBytesResumableInternal, - uploadString as uploadStringInternal, - getMetadata as getMetadataInternal, - updateMetadata as updateMetadataInternal, - list as listInternal, - listAll as listAllInternal, - getDownloadURL as getDownloadURLInternal, - deleteObject as deleteObjectInternal, - Reference, - _getChild as _getChildInternal -} from '../src/reference'; - -/** - * Public types. - */ -export * from './public-types'; - -export { Location as _Location } from '../src/implementation/location'; -export { UploadTask as _UploadTask } from '../src/task'; -export type { Reference as _Reference } from '../src/reference'; -export { FbsBlob as _FbsBlob } from '../src/implementation/blob'; - -/** - * Uploads data to this object's location. - * The upload is not resumable. - * @public - * @param ref - StorageReference where data should be uploaded. - * @param data - The data to upload. - * @param metadata - Metadata for the data to upload. - * @returns A Promise containing an UploadResult - */ -export function uploadBytes( - ref: StorageReference, - data: Blob | Uint8Array | ArrayBuffer, - metadata?: UploadMetadata -): Promise { - return uploadBytesInternal( - ref as Reference, - data, - metadata as MetadataInternal - ); -} - -/** - * Uploads a string to this object's location. - * The upload is not resumable. - * @public - * @param ref - StorageReference where string should be uploaded. - * @param value - The string to upload. - * @param format - The format of the string to upload. - * @param metadata - Metadata for the string to upload. - * @returns A Promise containing an UploadResult - */ -export function uploadString( - ref: StorageReference, - value: string, - format?: string, - metadata?: UploadMetadata -): Promise { - return uploadStringInternal( - ref as Reference, - value, - format, - metadata as MetadataInternal - ); -} - -/** - * Uploads data to this object's location. - * The upload can be paused and resumed, and exposes progress updates. - * @public - * @param ref - StorageReference where data should be uploaded. - * @param data - The data to upload. - * @param metadata - Metadata for the data to upload. - * @returns An UploadTask - */ -export function uploadBytesResumable( - ref: StorageReference, - data: Blob | Uint8Array | ArrayBuffer, - metadata?: UploadMetadata -): UploadTask { - return uploadBytesResumableInternal( - ref as Reference, - data, - metadata as MetadataInternal - ) as UploadTask; -} - -/** - * A promise that resolves with the metadata for this object. If this - * object doesn't exist or metadata cannot be retreived, the promise is - * rejected. - * @public - * @param ref - StorageReference to get metadata from. - */ -export function getMetadata(ref: StorageReference): Promise { - return getMetadataInternal(ref as Reference) as Promise; -} - -/** - * Updates the metadata for this object. - * @public - * @param ref - StorageReference to update metadata for. - * @param metadata - The new metadata for the object. - * Only values that have been explicitly set will be changed. Explicitly - * setting a value to null will remove the metadata. - * @returns A promise that resolves with the new metadata for this object. - */ -export function updateMetadata( - ref: StorageReference, - metadata: SettableMetadata -): Promise { - return updateMetadataInternal( - ref as Reference, - metadata as Partial - ) as Promise; -} - -/** - * List items (files) and prefixes (folders) under this storage reference. - * - * List API is only available for Firebase Rules Version 2. - * - * GCS is a key-blob store. Firebase Storage imposes the semantic of '/' - * delimited folder structure. - * Refer to GCS's List API if you want to learn more. - * - * To adhere to Firebase Rules's Semantics, Firebase Storage does not - * support objects whose paths end with "/" or contain two consecutive - * "/"s. Firebase Storage List API will filter these unsupported objects. - * list() may fail if there are too many unsupported objects in the bucket. - * @public - * - * @param ref - StorageReference to get list from. - * @param options - See ListOptions for details. - * @returns A Promise that resolves with the items and prefixes. - * `prefixes` contains references to sub-folders and `items` - * contains references to objects in this folder. `nextPageToken` - * can be used to get the rest of the results. - */ -export function list( - ref: StorageReference, - options?: ListOptions -): Promise { - return listInternal(ref as Reference, options); -} - -/** - * List all items (files) and prefixes (folders) under this storage reference. - * - * This is a helper method for calling list() repeatedly until there are - * no more results. The default pagination size is 1000. - * - * Note: The results may not be consistent if objects are changed while this - * operation is running. - * - * Warning: listAll may potentially consume too many resources if there are - * too many results. - * @public - * @param ref - StorageReference to get list from. - * - * @returns A Promise that resolves with all the items and prefixes under - * the current storage reference. `prefixes` contains references to - * sub-directories and `items` contains references to objects in this - * folder. `nextPageToken` is never returned. - */ -export function listAll(ref: StorageReference): Promise { - return listAllInternal(ref as Reference); -} +import { StorageService } from './public-types'; +import { STORAGE_TYPE } from './constants'; -/** - * Returns the download URL for the given Reference. - * @public - * @returns A promise that resolves with the download - * URL for this object. - */ -export function getDownloadURL(ref: StorageReference): Promise { - return getDownloadURLInternal(ref as Reference); -} - -/** - * Deletes the object at this location. - * @public - * @param ref - StorageReference for object to delete. - * @returns A promise that resolves if the deletion succeeds. - */ -export function deleteObject(ref: StorageReference): Promise { - return deleteObjectInternal(ref as Reference); -} - -/** - * Returns a StorageReference for the given url. - * @param storage - `StorageService` instance. - * @param url - URL. If empty, returns root reference. - * @public - */ -export function ref(storage: StorageService, url?: string): StorageReference; -/** - * Returns a StorageReference for the given path in the - * default bucket. - * @param storageOrRef - `StorageService` or `StorageReference`. - * @param pathOrUrlStorage - path. If empty, returns root reference (if Storage - * instance provided) or returns same reference (if Reference provided). - * @public - */ -export function ref( - storageOrRef: StorageService | StorageReference, - path?: string -): StorageReference; -export function ref( - serviceOrRef: StorageService | StorageReference, - pathOrUrl?: string -): StorageReference | null { - return refInternal( - serviceOrRef as StorageServiceInternal | Reference, - pathOrUrl - ); -} - -/** - * @internal - */ -export function _getChild(ref: StorageReference, childPath: string): Reference { - return _getChildInternal(ref as Reference, childPath); -} - -export { StringFormat } from '../src/implementation/string'; - -/** - * Type constant for Firebase Storage. - */ -const STORAGE_TYPE = 'storage-exp'; - -/** - * Gets a Firebase StorageService instance for the given Firebase app. - * @public - * @param app - Firebase app to get Storage instance for. - * @param bucketUrl - The gs:// url to your Firebase Storage Bucket. - * If not passed, uses the app's default Storage Bucket. - * @returns A Firebase StorageService instance. - */ -export function getStorage( - app: FirebaseApp, - bucketUrl?: string -): StorageService { - // Dependencies - const storageProvider: Provider<'storage-exp'> = _getProvider( - app, - STORAGE_TYPE - ); - const storageInstance = storageProvider.getImmediate({ - identifier: bucketUrl - }); - return storageInstance; -} +export * from './api'; function factory( container: ComponentContainer, diff --git a/packages/storage/rollup.config.compat.js b/packages/storage/rollup.config.compat.js index 2d154adc969..88ddbb893a7 100644 --- a/packages/storage/rollup.config.compat.js +++ b/packages/storage/rollup.config.compat.js @@ -36,7 +36,7 @@ const es5BuildPlugins = [ transformers: [ getImportPathTransformer({ // ../exp/index - pattern: /^.*exp\/index$/g, + pattern: /^.*exp\/api$/g, template: ['@firebase/storage'] }) ] @@ -74,7 +74,7 @@ const es2017BuildPlugins = [ transformers: [ getImportPathTransformer({ // ../exp/index - pattern: /^.*exp\/index$/g, + pattern: /^.*exp\/api$/g, template: ['@firebase/storage'] }) ], diff --git a/packages/storage/rollup.config.js b/packages/storage/rollup.config.js index e78b01ca5b2..1f5605ab56e 100644 --- a/packages/storage/rollup.config.js +++ b/packages/storage/rollup.config.js @@ -41,7 +41,10 @@ const es5Builds = [ { file: pkg.module, format: 'es', sourcemap: true } ], plugins: es5BuildPlugins, - external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)), + treeshake: { + moduleSideEffects: false + } } ]; @@ -69,7 +72,10 @@ const es2017Builds = [ sourcemap: true }, plugins: es2017BuildPlugins, - external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)), + treeshake: { + moduleSideEffects: false + } } ]; From a1317e0d17956ffb06615ef39af47730a60855d7 Mon Sep 17 00:00:00 2001 From: Feiyang1 Date: Mon, 15 Mar 2021 12:34:19 -0700 Subject: [PATCH 05/11] script for publishing storage-compat --- .../exp/prepare-firestore-for-exp-release.ts | 108 ++++------------- .../exp/prepare-storage-for-exp-release.ts | 32 ++++- scripts/exp/prepare-util.ts | 114 ++++++++++++++++++ scripts/exp/release.ts | 6 +- 4 files changed, 172 insertions(+), 88 deletions(-) create mode 100644 scripts/exp/prepare-util.ts diff --git a/scripts/exp/prepare-firestore-for-exp-release.ts b/scripts/exp/prepare-firestore-for-exp-release.ts index fd160b86644..061414d33b6 100644 --- a/scripts/exp/prepare-firestore-for-exp-release.ts +++ b/scripts/exp/prepare-firestore-for-exp-release.ts @@ -17,16 +17,12 @@ import { resolve } from 'path'; import { projectRoot, readPackageJson } from '../utils'; +import { writeFileSync, existsSync, rmdirSync } from 'fs'; import { - writeFileSync, - statSync, - readFileSync, - existsSync, - rmdirSync, - readdirSync, - mkdirSync, - copyFileSync -} from 'fs'; + copyRecursiveSync, + createCompatProject, + transformFile +} from './prepare-util'; const packagePath = `${projectRoot}/packages/firestore`; @@ -80,84 +76,24 @@ export async function prepare() { ); } -const FIRESTORE_SRC = resolve(projectRoot, 'packages/firestore'); -const FIRESTORE_COMPAT_SRC = resolve(projectRoot, 'packages/firestore/compat'); -const FIRESTORE_COMPAT_DEST = resolve( - projectRoot, - 'packages-exp/firestore-compat' -); -const FIRESTORE_COMPAT_BINARY_SRC = resolve(FIRESTORE_SRC, 'dist/compat'); -const FIRESTORE_COMPAT_BINARY_DEST = resolve(FIRESTORE_COMPAT_DEST, 'dist'); - export async function createFirestoreCompatProject() { - // remove the dir if it exists - if (existsSync(FIRESTORE_COMPAT_DEST)) { - rmdirSync(FIRESTORE_COMPAT_DEST, { recursive: true }); - } - - copyRecursiveSync(FIRESTORE_COMPAT_SRC, FIRESTORE_COMPAT_DEST); - copyRecursiveSync( - FIRESTORE_COMPAT_BINARY_SRC, - FIRESTORE_COMPAT_BINARY_DEST, - /* include d.ts files*/ true + const FIRESTORE_SRC = resolve(projectRoot, 'packages/firestore'); + const FIRESTORE_COMPAT_SRC = resolve( + projectRoot, + 'packages/firestore/compat' ); - - // update root package.json - await transformFile( - resolve(FIRESTORE_COMPAT_DEST, 'package.json'), - async content => { - const updatedContent = content.replace(/\.\.\/dist\/compat/g, './dist'); - const compatPkgJson = JSON.parse(updatedContent); - - const firestorePkgJson = await readPackageJson(FIRESTORE_SRC); - - compatPkgJson.dependencies = { - ...firestorePkgJson.dependencies, - '@firebase/firestore': '0.0.900' - }; - - compatPkgJson.peerDependencies = { - '@firebase/app': '0.x' - }; - - compatPkgJson.files = ['dist']; - - return `${JSON.stringify(compatPkgJson, null, 2)}\n`; - } + const FIRESTORE_COMPAT_DEST = resolve( + projectRoot, + 'packages-exp/firestore-compat' ); -} - -function copyRecursiveSync( - src: string, - dest: string, - includeTs: boolean = false -) { - if (!existsSync(src)) { - return; - } - - const srcStat = statSync(src); - const isDirectory = srcStat.isDirectory(); - if (isDirectory) { - mkdirSync(dest); - for (const item of readdirSync(src)) { - copyRecursiveSync(resolve(src, item), resolve(dest, item), includeTs); - } - } else { - // do not copy source file - if (src.includes('.ts') && !includeTs) { - return; - } - - copyFileSync(src, dest); - } -} - -async function transformFile( - path: string, - transformer: (content: string) => Promise -) { - let content = readFileSync(path, 'utf8'); - - writeFileSync(path, await transformer(content), { encoding: 'utf8' }); + const FIRESTORE_COMPAT_BINARY_SRC = resolve(FIRESTORE_SRC, 'dist/compat'); + const FIRESTORE_COMPAT_BINARY_DEST = resolve(FIRESTORE_COMPAT_DEST, 'dist'); + + createCompatProject({ + srcDir: FIRESTORE_SRC, + compatSrcDir: FIRESTORE_COMPAT_SRC, + compatDestDir: FIRESTORE_COMPAT_DEST, + compatBinarySrcDir: FIRESTORE_COMPAT_BINARY_SRC, + compatBinaryDestDir: FIRESTORE_COMPAT_BINARY_DEST + }); } diff --git a/scripts/exp/prepare-storage-for-exp-release.ts b/scripts/exp/prepare-storage-for-exp-release.ts index 116774c010d..48a3d50acab 100644 --- a/scripts/exp/prepare-storage-for-exp-release.ts +++ b/scripts/exp/prepare-storage-for-exp-release.ts @@ -16,8 +16,19 @@ */ import { projectRoot, readPackageJson } from '../utils'; -import { writeFile as _writeFile, readFile as _readFile } from 'fs'; +import { + writeFile as _writeFile, + readFile as _readFile, + existsSync, + rmdirSync +} from 'fs'; +import { resolve } from 'path'; import { promisify } from 'util'; +import { + copyRecursiveSync, + createCompatProject, + transformFile +} from './prepare-util'; const writeFile = promisify(_writeFile); const packagePath = `${projectRoot}/packages/storage`; @@ -60,3 +71,22 @@ export async function prepare() { { encoding: 'utf-8' } ); } + +export async function createStorageCompatProject() { + const STORAGE_SRC = resolve(projectRoot, 'packages/storage'); + const STORAGE_COMPAT_SRC = resolve(projectRoot, 'packages/storage/compat'); + const STORAGE_COMPAT_DEST = resolve( + projectRoot, + 'packages-exp/storage-compat' + ); + const STORAGE_COMPAT_BINARY_SRC = resolve(STORAGE_SRC, 'dist/compat'); + const STORAGE_COMPAT_BINARY_DEST = resolve(STORAGE_COMPAT_DEST, 'dist'); + + createCompatProject({ + srcDir: STORAGE_SRC, + compatSrcDir: STORAGE_COMPAT_SRC, + compatDestDir: STORAGE_COMPAT_DEST, + compatBinarySrcDir: STORAGE_COMPAT_BINARY_SRC, + compatBinaryDestDir: STORAGE_COMPAT_BINARY_DEST + }); +} diff --git a/scripts/exp/prepare-util.ts b/scripts/exp/prepare-util.ts new file mode 100644 index 00000000000..bac797770d1 --- /dev/null +++ b/scripts/exp/prepare-util.ts @@ -0,0 +1,114 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { resolve } from 'path'; +import { + writeFileSync, + statSync, + readFileSync, + existsSync, + readdirSync, + mkdirSync, + copyFileSync, + rmdirSync +} from 'fs'; +import { readPackageJson } from '../utils'; + +export interface CompatConfig { + srcDir: string; + compatSrcDir: string; + compatDestDir: string; + compatBinarySrcDir: string; + compatBinaryDestDir: string; +} + +export async function createCompatProject(config: CompatConfig) { + const { + srcDir, + compatSrcDir, + compatDestDir, + compatBinarySrcDir, + compatBinaryDestDir + } = config; + // remove the dir if it exists + if (existsSync(compatDestDir)) { + rmdirSync(compatDestDir, { recursive: true }); + } + + copyRecursiveSync(compatSrcDir, compatDestDir); + copyRecursiveSync( + compatBinarySrcDir, + compatBinaryDestDir, + /* include d.ts files*/ true + ); + + // update root package.json + await transformFile(resolve(compatDestDir, 'package.json'), async content => { + const updatedContent = content.replace(/\.\.\/dist\/compat/g, './dist'); + const compatPkgJson = JSON.parse(updatedContent); + + const srcPkgJson = await readPackageJson(srcDir); + + compatPkgJson.dependencies = { + ...srcPkgJson.dependencies, + [srcPkgJson.name]: '0.0.900' + }; + + compatPkgJson.peerDependencies = { + '@firebase/app': '0.x' + }; + + compatPkgJson.files = ['dist']; + + return `${JSON.stringify(compatPkgJson, null, 2)}\n`; + }); +} + +export function copyRecursiveSync( + src: string, + dest: string, + includeTs: boolean = false +) { + if (!existsSync(src)) { + return; + } + + const srcStat = statSync(src); + const isDirectory = srcStat.isDirectory(); + if (isDirectory) { + mkdirSync(dest); + for (const item of readdirSync(src)) { + copyRecursiveSync(resolve(src, item), resolve(dest, item), includeTs); + } + } else { + // do not copy source file + if (src.includes('.ts') && !includeTs) { + return; + } + + copyFileSync(src, dest); + } +} + +export async function transformFile( + path: string, + transformer: (content: string) => Promise +) { + let content = readFileSync(path, 'utf8'); + + writeFileSync(path, await transformer(content), { encoding: 'utf8' }); +} diff --git a/scripts/exp/release.ts b/scripts/exp/release.ts index 258b6ac80a2..e3a44b0e115 100644 --- a/scripts/exp/release.ts +++ b/scripts/exp/release.ts @@ -32,7 +32,10 @@ import { prepare as prepareFirestoreForRelease, createFirestoreCompatProject } from './prepare-firestore-for-exp-release'; -import { prepare as prepareStorageForRelease } from './prepare-storage-for-exp-release'; +import { + createStorageCompatProject, + prepare as prepareStorageForRelease +} from './prepare-storage-for-exp-release'; import { prepare as prepareDatabaseForRelease } from './prepare-database-for-exp-release'; import * as yargs from 'yargs'; @@ -74,6 +77,7 @@ async function publishExpPackages({ dryRun }: { dryRun: boolean }) { * Create compat packages for Firestore, Database and Storage */ await createFirestoreCompatProject(); + await createStorageCompatProject(); /** * build firebase From 52c1c400cf1474645e2ccc3bbe4713c5b5caf7a0 Mon Sep 17 00:00:00 2001 From: Feiyang1 Date: Mon, 15 Mar 2021 12:40:50 -0700 Subject: [PATCH 06/11] remove unused imports --- scripts/exp/prepare-firestore-for-exp-release.ts | 8 ++------ scripts/exp/prepare-storage-for-exp-release.ts | 13 ++----------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/scripts/exp/prepare-firestore-for-exp-release.ts b/scripts/exp/prepare-firestore-for-exp-release.ts index 061414d33b6..1df5571afcf 100644 --- a/scripts/exp/prepare-firestore-for-exp-release.ts +++ b/scripts/exp/prepare-firestore-for-exp-release.ts @@ -17,12 +17,8 @@ import { resolve } from 'path'; import { projectRoot, readPackageJson } from '../utils'; -import { writeFileSync, existsSync, rmdirSync } from 'fs'; -import { - copyRecursiveSync, - createCompatProject, - transformFile -} from './prepare-util'; +import { writeFileSync } from 'fs'; +import { createCompatProject } from './prepare-util'; const packagePath = `${projectRoot}/packages/firestore`; diff --git a/scripts/exp/prepare-storage-for-exp-release.ts b/scripts/exp/prepare-storage-for-exp-release.ts index 48a3d50acab..ca2f3fc9ff9 100644 --- a/scripts/exp/prepare-storage-for-exp-release.ts +++ b/scripts/exp/prepare-storage-for-exp-release.ts @@ -16,19 +16,10 @@ */ import { projectRoot, readPackageJson } from '../utils'; -import { - writeFile as _writeFile, - readFile as _readFile, - existsSync, - rmdirSync -} from 'fs'; +import { writeFile as _writeFile, readFile as _readFile } from 'fs'; import { resolve } from 'path'; import { promisify } from 'util'; -import { - copyRecursiveSync, - createCompatProject, - transformFile -} from './prepare-util'; +import { createCompatProject } from './prepare-util'; const writeFile = promisify(_writeFile); const packagePath = `${projectRoot}/packages/storage`; From 716da6cd25372ca857d3ace99948c211168ae31c Mon Sep 17 00:00:00 2001 From: Feiyang1 Date: Mon, 15 Mar 2021 12:43:39 -0700 Subject: [PATCH 07/11] add build script --- packages/storage/package.json | 1 + scripts/exp/release.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/storage/package.json b/packages/storage/package.json index b13f5749958..0476d80aeed 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -17,6 +17,7 @@ "build": "rollup -c rollup.config.js && yarn build:exp", "build:exp": "rollup -c rollup.config.exp.js ; yarn api-report", "build:compat": "rollup -c rollup.config.compat.js", + "build:exp:release": "run-p build:exp build:compat", "build:deps": "lerna run --scope @firebase/storage --include-dependencies build", "dev": "rollup -c -w", "test": "run-p test:browser lint", diff --git a/scripts/exp/release.ts b/scripts/exp/release.ts index e3a44b0e115..92c3044f3ca 100644 --- a/scripts/exp/release.ts +++ b/scripts/exp/release.ts @@ -273,7 +273,7 @@ async function buildPackages() { // Storage await spawn( 'yarn', - ['lerna', 'run', '--scope', '@firebase/storage', 'build:exp'], + ['lerna', 'run', '--scope', '@firebase/storage', 'build:exp:release'], { cwd: projectRoot, stdio: 'inherit' From 1f5ed0ec15641a49f7bc34e0a7b1a18908cece55 Mon Sep 17 00:00:00 2001 From: Feiyang1 Date: Mon, 15 Mar 2021 15:20:29 -0700 Subject: [PATCH 08/11] simplify release build --- packages-exp/analytics-compat/rollup.shared.js | 7 ++++--- packages-exp/app-compat/rollup.config.release.js | 7 ++++--- packages-exp/functions-compat/rollup.config.base.js | 7 ++++--- packages-exp/performance-compat/rollup.shared.js | 7 ++++--- packages-exp/remote-config-compat/rollup.shared.js | 7 ++++--- scripts/exp/release.ts | 13 ------------- 6 files changed, 20 insertions(+), 28 deletions(-) diff --git a/packages-exp/analytics-compat/rollup.shared.js b/packages-exp/analytics-compat/rollup.shared.js index 328d06b4a02..b108a374e39 100644 --- a/packages-exp/analytics-compat/rollup.shared.js +++ b/packages-exp/analytics-compat/rollup.shared.js @@ -16,9 +16,10 @@ */ import pkg from './package.json'; -const deps = Object.keys( - Object.assign({}, pkg.peerDependencies, pkg.dependencies) -); +const deps = [ + ...Object.keys(Object.assign({}, pkg.peerDependencies, pkg.dependencies)), + '@firebase/analytics' +]; export const es5BuildsNoPlugin = [ /** diff --git a/packages-exp/app-compat/rollup.config.release.js b/packages-exp/app-compat/rollup.config.release.js index a38c8a03d41..8b1615cecb4 100644 --- a/packages-exp/app-compat/rollup.config.release.js +++ b/packages-exp/app-compat/rollup.config.release.js @@ -21,9 +21,10 @@ import typescript from 'typescript'; import pkg from './package.json'; import { importPathTransformer } from '../../scripts/exp/ts-transform-import-path'; -const deps = Object.keys( - Object.assign({}, pkg.peerDependencies, pkg.dependencies) -); +const deps = [ + ...Object.keys(Object.assign({}, pkg.peerDependencies, pkg.dependencies)), + '@firebase/app' +]; /** * ES5 Builds diff --git a/packages-exp/functions-compat/rollup.config.base.js b/packages-exp/functions-compat/rollup.config.base.js index ebb941e4225..515b3318db1 100644 --- a/packages-exp/functions-compat/rollup.config.base.js +++ b/packages-exp/functions-compat/rollup.config.base.js @@ -20,9 +20,10 @@ import typescriptPlugin from 'rollup-plugin-typescript2'; import typescript from 'typescript'; import pkg from './package.json'; -const deps = Object.keys( - Object.assign({}, pkg.peerDependencies, pkg.dependencies) -); +const deps = [ + ...Object.keys(Object.assign({}, pkg.peerDependencies, pkg.dependencies)), + '@firebase/functions' +]; /** * ES5 Builds diff --git a/packages-exp/performance-compat/rollup.shared.js b/packages-exp/performance-compat/rollup.shared.js index 5474a15ba7c..0e0c66a8b72 100644 --- a/packages-exp/performance-compat/rollup.shared.js +++ b/packages-exp/performance-compat/rollup.shared.js @@ -17,9 +17,10 @@ import pkg from './package.json'; -const deps = Object.keys( - Object.assign({}, pkg.peerDependencies, pkg.dependencies) -); +const deps = [ + ...Object.keys(Object.assign({}, pkg.peerDependencies, pkg.dependencies)), + '@firebase/performance' +]; export const es5BuildsNoPlugin = [ /** diff --git a/packages-exp/remote-config-compat/rollup.shared.js b/packages-exp/remote-config-compat/rollup.shared.js index 5474a15ba7c..25fdad9a004 100644 --- a/packages-exp/remote-config-compat/rollup.shared.js +++ b/packages-exp/remote-config-compat/rollup.shared.js @@ -17,9 +17,10 @@ import pkg from './package.json'; -const deps = Object.keys( - Object.assign({}, pkg.peerDependencies, pkg.dependencies) -); +const deps = [ + ...Object.keys(Object.assign({}, pkg.peerDependencies, pkg.dependencies)), + '@firebase/remote-config' +]; export const es5BuildsNoPlugin = [ /** diff --git a/scripts/exp/release.ts b/scripts/exp/release.ts index 92c3044f3ca..5678184883f 100644 --- a/scripts/exp/release.ts +++ b/scripts/exp/release.ts @@ -204,19 +204,6 @@ async function buildPackages() { 'lerna', 'run', '--scope', - // We replace `@firebase/app-exp` with `@firebase/app` during compilation, so we need to - // compile @firebase/app first to make rollup happy though it's not an actual dependency. - '@firebase/app', - '--scope', - // the same reason above - '@firebase/functions', - '--scope', - // the same reason above - '@firebase/remote-config', - '--scope', - // the same reason above - '@firebase/analytics', - '--scope', '@firebase/util', '--scope', '@firebase/component', From 6129d07d9866ca82bb624de8f03a4d4440509430 Mon Sep 17 00:00:00 2001 From: Feiyang1 Date: Mon, 15 Mar 2021 23:20:03 -0700 Subject: [PATCH 09/11] make compat work in runtime --- packages/storage/compat/index.ts | 21 ++++------ packages/storage/compat/package.json | 2 +- packages/storage/index.ts | 34 +--------------- packages/storage/register-module.ts | 50 ++++++++++++++++++++++++ packages/storage/rollup.config.compat.js | 10 ++++- 5 files changed, 69 insertions(+), 48 deletions(-) create mode 100644 packages/storage/register-module.ts diff --git a/packages/storage/compat/index.ts b/packages/storage/compat/index.ts index 9239b3ca46e..d408890cc50 100644 --- a/packages/storage/compat/index.ts +++ b/packages/storage/compat/index.ts @@ -20,10 +20,8 @@ import { _FirebaseNamespace } from '@firebase/app-types/private'; import { StringFormat } from '../src/implementation/string'; import { TaskEvent, TaskState } from '../src/implementation/taskenums'; -import { XhrIoPool } from '../src/implementation/xhriopool'; import { ReferenceCompat } from './reference'; import { StorageServiceCompat } from './service'; -import { StorageService } from '../src/service'; import * as types from '@firebase/storage-types'; import { Component, @@ -34,6 +32,8 @@ import { import { name, version } from '../package.json'; +import '../register-module'; + /** * Type constant for Firebase Storage. */ @@ -44,21 +44,16 @@ function factory( { instanceIdentifier: url }: InstanceFactoryOptions ): types.FirebaseStorage { // Dependencies - // TODO: This should eventually be 'app-compat' - const app = container.getProvider('app').getImmediate(); - const authProvider = container.getProvider('auth-internal'); + const app = container.getProvider('app-compat').getImmediate(); + const storageExp = container + .getProvider('storage-exp') + .getImmediate({ identifier: url }); // TODO: get StorageService instance from component framework instead // of creating a new one. const storageServiceCompat: StorageServiceCompat = new StorageServiceCompat( app, - new StorageService( - app, - authProvider, - new XhrIoPool(), - url, - firebase.SDK_VERSION - ) + storageExp ); return storageServiceCompat; } @@ -69,7 +64,7 @@ export function registerStorage(instance: _FirebaseNamespace): void { TaskState, TaskEvent, StringFormat, - Storage: StorageService, + Storage: StorageServiceCompat, Reference: ReferenceCompat }; instance.INTERNAL.registerComponent( diff --git a/packages/storage/compat/package.json b/packages/storage/compat/package.json index c51e9d6769c..83bada2dd5a 100644 --- a/packages/storage/compat/package.json +++ b/packages/storage/compat/package.json @@ -8,6 +8,6 @@ "module": "../dist/compat/esm5/index.js", "esm2017": "../dist/compat/esm2017/index.js", "license": "Apache-2.0", - "typings": "../dist/compat/esm5/packages/firestore/compat/index.d.ts" + "typings": "../dist/compat/esm5/compat/index.d.ts" } \ No newline at end of file diff --git a/packages/storage/index.ts b/packages/storage/index.ts index 5d1596c75be..8e42fb3ad71 100644 --- a/packages/storage/index.ts +++ b/packages/storage/index.ts @@ -34,6 +34,8 @@ import { import { name, version } from './package.json'; +import './register-module'; + /** * Type constant for Firebase Storage. */ @@ -82,35 +84,3 @@ export function registerStorage(instance: _FirebaseNamespace): void { } registerStorage(firebase as _FirebaseNamespace); - -/** - * Define extension behavior for `registerStorage` - */ -declare module '@firebase/app-types' { - interface FirebaseNamespace { - storage?: { - (app?: FirebaseApp, url?: string): types.FirebaseStorage; - Storage: typeof types.FirebaseStorage; - - StringFormat: { - BASE64: types.StringFormat; - BASE64URL: types.StringFormat; - DATA_URL: types.StringFormat; - RAW: types.StringFormat; - }; - TaskEvent: { - STATE_CHANGED: types.TaskEvent; - }; - TaskState: { - CANCELED: types.TaskState; - ERROR: types.TaskState; - PAUSED: types.TaskState; - RUNNING: types.TaskState; - SUCCESS: types.TaskState; - }; - }; - } - interface FirebaseApp { - storage?(storageBucket?: string): types.FirebaseStorage; - } -} diff --git a/packages/storage/register-module.ts b/packages/storage/register-module.ts new file mode 100644 index 00000000000..23d09759347 --- /dev/null +++ b/packages/storage/register-module.ts @@ -0,0 +1,50 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as types from '@firebase/storage-types'; + +/** + * Define extension behavior for `registerStorage` + */ +declare module '@firebase/app-types' { + interface FirebaseNamespace { + storage?: { + (app?: FirebaseApp, url?: string): types.FirebaseStorage; + Storage: typeof types.FirebaseStorage; + + StringFormat: { + BASE64: types.StringFormat; + BASE64URL: types.StringFormat; + DATA_URL: types.StringFormat; + RAW: types.StringFormat; + }; + TaskEvent: { + STATE_CHANGED: types.TaskEvent; + }; + TaskState: { + CANCELED: types.TaskState; + ERROR: types.TaskState; + PAUSED: types.TaskState; + RUNNING: types.TaskState; + SUCCESS: types.TaskState; + }; + }; + } + interface FirebaseApp { + storage?(storageBucket?: string): types.FirebaseStorage; + } +} diff --git a/packages/storage/rollup.config.compat.js b/packages/storage/rollup.config.compat.js index 88ddbb893a7..2bd37b59444 100644 --- a/packages/storage/rollup.config.compat.js +++ b/packages/storage/rollup.config.compat.js @@ -60,7 +60,10 @@ const es5Builds = [ } ], plugins: es5BuildPlugins, - external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)), + treeshake: { + moduleSideEffects: false + } } ]; @@ -96,7 +99,10 @@ const es2017Builds = [ sourcemap: true }, plugins: es2017BuildPlugins, - external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)), + treeshake: { + moduleSideEffects: false + } } ]; From 85788f0e2f391bb5b56314894e590aba7599f5d9 Mon Sep 17 00:00:00 2001 From: Feiyang1 Date: Tue, 16 Mar 2021 10:45:16 -0700 Subject: [PATCH 10/11] fix misc things --- common/api-review/storage.api.md | 87 +++++++++++++++++++++++++++++++- packages/storage/compat/index.ts | 1 + packages/storage/exp/api.ts | 1 - packages/storage/exp/index.ts | 1 - packages/storage/package.json | 3 +- packages/storage/src/task.ts | 2 +- 6 files changed, 90 insertions(+), 5 deletions(-) diff --git a/common/api-review/storage.api.md b/common/api-review/storage.api.md index 218e82a442d..988b0fcc493 100644 --- a/common/api-review/storage.api.md +++ b/common/api-review/storage.api.md @@ -6,14 +6,32 @@ import { CompleteFn } from '@firebase/util'; import { FirebaseApp } from '@firebase/app'; +import { FirebaseAuthInternalName } from '@firebase/auth-interop-types'; import { FirebaseError } from '@firebase/util'; +import { _FirebaseService } from '@firebase/app'; import { NextFn } from '@firebase/util'; +import { Provider } from '@firebase/component'; import { Subscribe } from '@firebase/util'; import { Unsubscribe } from '@firebase/util'; // @public export function deleteObject(ref: StorageReference): Promise; +// @internal (undocumented) +export class _FbsBlob { + constructor(data: Blob | Uint8Array | ArrayBuffer, elideCopy?: boolean); + // (undocumented) + static getBlob(...args: Array): _FbsBlob | null; + // (undocumented) + size(): number; + // (undocumented) + slice(startByte: number, endByte: number): _FbsBlob | null; + // (undocumented) + type(): string; + // (undocumented) + uploadData(): Blob | Uint8Array; +} + // @public export interface FirebaseStorageError extends FirebaseError { serverResponse: string | null; @@ -33,6 +51,9 @@ export interface FullMetadata extends UploadMetadata { updated: string; } +// @internal (undocumented) +export function _getChild(ref: StorageReference, childPath: string): _Reference; + // @public export function getDownloadURL(ref: StorageReference): Promise; @@ -61,12 +82,50 @@ export interface ListResult { prefixes: StorageReference[]; } +// @internal +export class _Location { + constructor(bucket: string, path: string); + // (undocumented) + readonly bucket: string; + // (undocumented) + bucketOnlyServerUrl(): string; + // (undocumented) + fullServerUrl(): string; + // (undocumented) + get isRoot(): boolean; + // (undocumented) + static makeFromBucketSpec(bucketString: string): _Location; + // (undocumented) + static makeFromUrl(url: string): _Location; + // (undocumented) + get path(): string; + } + // @public export function ref(storage: StorageService, url?: string): StorageReference; // @public export function ref(storageOrRef: StorageService | StorageReference, path?: string): StorageReference; +// @internal +export class _Reference { + // Warning: (ae-forgotten-export) The symbol "StorageService" needs to be exported by the entry point index.d.ts + constructor(_service: StorageService_2, location: string | _Location); + get bucket(): string; + get fullPath(): string; + // (undocumented) + _location: _Location; + get name(): string; + // (undocumented) + protected _newRef(service: StorageService_2, location: _Location): _Reference; + get parent(): _Reference | null; + get root(): _Reference; + get storage(): StorageService_2; + _throwIfRoot(name: string): void; + // @override + toString(): string; +} + // @public export interface SettableMetadata { cacheControl?: string | undefined; @@ -101,7 +160,7 @@ export interface StorageReference { } // @public -export interface StorageService { +export interface StorageService extends _FirebaseService { readonly app: FirebaseApp; maxOperationRetryTime: number; maxUploadRetryTime: number; @@ -158,6 +217,32 @@ export interface UploadTask { then(onFulfilled?: ((snapshot: UploadTaskSnapshot) => unknown) | null, onRejected?: ((error: FirebaseStorageError) => unknown) | null): Promise; } +// @internal +export class _UploadTask { + constructor(ref: _Reference, blob: _FbsBlob, metadata?: Metadata | null); + _blob: _FbsBlob; + cancel(): boolean; + catch(onRejected: (p1: FirebaseStorageError_2) => T | Promise): Promise; + // Warning: (ae-forgotten-export) The symbol "Metadata" needs to be exported by the entry point index.d.ts + _metadata: Metadata | null; + // Warning: (ae-forgotten-export) The symbol "TaskEvent" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "StorageObserver" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "ErrorFn" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "CompleteFn" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "Unsubscribe" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "Subscribe" needs to be exported by the entry point index.d.ts + on(type: TaskEvent_2, nextOrObserver?: StorageObserver_2 | ((a: UploadTaskSnapshot_2) => unknown), error?: ErrorFn, completed?: CompleteFn_2): Unsubscribe_2 | Subscribe_2; + pause(): boolean; + resume(): boolean; + // Warning: (ae-forgotten-export) The symbol "UploadTaskSnapshot" needs to be exported by the entry point index.d.ts + get snapshot(): UploadTaskSnapshot_2; + // Warning: (ae-forgotten-export) The symbol "InternalTaskState" needs to be exported by the entry point index.d.ts + _state: InternalTaskState; + // Warning: (ae-forgotten-export) The symbol "FirebaseStorageError" needs to be exported by the entry point index.d.ts + then(onFulfilled?: ((value: UploadTaskSnapshot_2) => U | Promise) | null, onRejected?: ((error: FirebaseStorageError_2) => U | Promise) | null): Promise; + _transferred: number; + } + // @public export interface UploadTaskSnapshot { bytesTransferred: number; diff --git a/packages/storage/compat/index.ts b/packages/storage/compat/index.ts index d408890cc50..ef29d5610ce 100644 --- a/packages/storage/compat/index.ts +++ b/packages/storage/compat/index.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +// eslint-disable-next-line import/no-extraneous-dependencies import firebase from '@firebase/app-compat'; import { _FirebaseNamespace } from '@firebase/app-types/private'; import { StringFormat } from '../src/implementation/string'; diff --git a/packages/storage/exp/api.ts b/packages/storage/exp/api.ts index e3448306ff7..092d333be7a 100644 --- a/packages/storage/exp/api.ts +++ b/packages/storage/exp/api.ts @@ -16,7 +16,6 @@ */ import { - _registerComponent, _getProvider, FirebaseApp // eslint-disable-next-line import/no-extraneous-dependencies diff --git a/packages/storage/exp/index.ts b/packages/storage/exp/index.ts index 6c33e2b854d..670081acbf6 100644 --- a/packages/storage/exp/index.ts +++ b/packages/storage/exp/index.ts @@ -18,7 +18,6 @@ import { _registerComponent, registerVersion, - _getProvider, SDK_VERSION // eslint-disable-next-line import/no-extraneous-dependencies } from '@firebase/app-exp'; diff --git a/packages/storage/package.json b/packages/storage/package.json index 0476d80aeed..d415f568f60 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -12,9 +12,10 @@ "exp/dist" ], "scripts": { + "bundle": "rollup -c", "lint": "eslint -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'", "lint:fix": "eslint --fix -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'", - "build": "rollup -c rollup.config.js && yarn build:exp", + "build": "run-p 'bundle rollup.config.js' build:exp build:compat", "build:exp": "rollup -c rollup.config.exp.js ; yarn api-report", "build:compat": "rollup -c rollup.config.compat.js", "build:exp:release": "run-p build:exp build:compat", diff --git a/packages/storage/src/task.ts b/packages/storage/src/task.ts index 4a66ae79294..ebe8f88ef40 100644 --- a/packages/storage/src/task.ts +++ b/packages/storage/src/task.ts @@ -57,7 +57,7 @@ import { Reference } from './reference'; /** * Represents a blob being uploaded. Can be used to pause/resume/cancel the * upload and manage callbacks for various events. - * @public + * @internal */ export class UploadTask { private _ref: Reference; From 012eb11ad651e9256e8dde68a195981a8b991695 Mon Sep 17 00:00:00 2001 From: Feiyang1 Date: Tue, 16 Mar 2021 12:27:33 -0700 Subject: [PATCH 11/11] fix tests --- packages/storage/compat/index.ts | 2 -- packages/storage/package.json | 1 + .../storage/test/integration/integration.compat.test.ts | 2 +- packages/storage/test/unit/index.compat.test.ts | 9 ++++++--- packages/storage/test/unit/service.compat.test.ts | 2 +- packages/storage/test/unit/service.exp.test.ts | 2 +- packages/storage/test/unit/task.test.ts | 4 ++-- 7 files changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/storage/compat/index.ts b/packages/storage/compat/index.ts index ef29d5610ce..b5a749730f0 100644 --- a/packages/storage/compat/index.ts +++ b/packages/storage/compat/index.ts @@ -50,8 +50,6 @@ function factory( .getProvider('storage-exp') .getImmediate({ identifier: url }); - // TODO: get StorageService instance from component framework instead - // of creating a new one. const storageServiceCompat: StorageServiceCompat = new StorageServiceCompat( app, storageExp diff --git a/packages/storage/package.json b/packages/storage/package.json index d415f568f60..bee6e0d84c3 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -30,6 +30,7 @@ "test:browser:compat": "karma start --single-run --compat", "test:browser:exp": "karma start --single-run --exp", "test:browser": "karma start --single-run", + "test:debug": "karma start --browser=Chrome", "prettier": "prettier --write 'src/**/*.ts' 'test/**/*.ts'", "api-report": "api-extractor run --local --verbose && ts-node-script ../../repo-scripts/prune-dts/prune-dts.ts --input exp/dist/storage-public.d.ts --output exp/dist/storage-public.d.ts" }, diff --git a/packages/storage/test/integration/integration.compat.test.ts b/packages/storage/test/integration/integration.compat.test.ts index 2cf07bad38b..3c93265677d 100644 --- a/packages/storage/test/integration/integration.compat.test.ts +++ b/packages/storage/test/integration/integration.compat.test.ts @@ -23,7 +23,7 @@ import '@firebase/auth'; import * as storage from '@firebase/storage-types'; import { expect } from 'chai'; -import '../../compat/index'; +import '../../index'; // eslint-disable-next-line @typescript-eslint/no-require-imports const PROJECT_CONFIG = require('../../../../config/project.json'); diff --git a/packages/storage/test/unit/index.compat.test.ts b/packages/storage/test/unit/index.compat.test.ts index c01c82d73d2..cb62db5ada8 100644 --- a/packages/storage/test/unit/index.compat.test.ts +++ b/packages/storage/test/unit/index.compat.test.ts @@ -15,10 +15,11 @@ * limitations under the License. */ import { expect } from 'chai'; -import '../../compat/index'; +import '../../index'; import firebase from '@firebase/app'; // eslint-disable-next-line import/no-extraneous-dependencies import { StorageServiceCompat } from '../../compat/service'; +import { StorageService } from '../../src/service'; // eslint-disable-next-line @typescript-eslint/no-require-imports const PROJECT_CONFIG = require('../../../../config/project.json'); @@ -38,7 +39,8 @@ describe('Firebase Storage > API', () => { }); const storage = firebase.storage!(); expect( - (storage as StorageServiceCompat)._delegate._bucket?.bucket + ((storage as StorageServiceCompat)._delegate as StorageService)._bucket + ?.bucket ).to.equal(STORAGE_BUCKET); await app.delete(); }); @@ -51,7 +53,8 @@ describe('Firebase Storage > API', () => { }); const storage = firebase.storage!(app, 'gs://foo-bar.appspot.com'); expect( - (storage as StorageServiceCompat)._delegate._bucket?.bucket + ((storage as StorageServiceCompat)._delegate as StorageService)._bucket + ?.bucket ).to.equal(STORAGE_BUCKET); await app.delete(); }); diff --git a/packages/storage/test/unit/service.compat.test.ts b/packages/storage/test/unit/service.compat.test.ts index a7502f531ca..67886b9139a 100644 --- a/packages/storage/test/unit/service.compat.test.ts +++ b/packages/storage/test/unit/service.compat.test.ts @@ -298,7 +298,7 @@ GOOG4-RSA-SHA256` }); it('Running uploads fail when the service is deleted', () => { const ref = service.refFromURL('gs://mybucket/image.jpg'); - const toReturn = new Promise((resolve, reject) => { + const toReturn = new Promise((resolve, reject) => { ref.put(new Blob(['a'])).on( TaskEvent.STATE_CHANGED, null, diff --git a/packages/storage/test/unit/service.exp.test.ts b/packages/storage/test/unit/service.exp.test.ts index 941c0507cb1..eee6568e2ec 100644 --- a/packages/storage/test/unit/service.exp.test.ts +++ b/packages/storage/test/unit/service.exp.test.ts @@ -298,7 +298,7 @@ GOOG4-RSA-SHA256` }); it('Running uploads fail when the service is deleted', () => { const reference = ref(service, 'gs://mybucket/image.jpg'); - const toReturn = new Promise((resolve, reject) => { + const toReturn = new Promise((resolve, reject) => { uploadBytesResumable(reference, new Blob(['a'])).on( TaskEvent.STATE_CHANGED, undefined, diff --git a/packages/storage/test/unit/task.test.ts b/packages/storage/test/unit/task.test.ts index d2c6d98eff7..f337b5e259a 100644 --- a/packages/storage/test/unit/task.test.ts +++ b/packages/storage/test/unit/task.test.ts @@ -115,7 +115,7 @@ describe('Firebase Storage > Upload Task', () => { h1(); h2(); - return new Promise(resolve => { + return new Promise(resolve => { task.on( TaskEvent.STATE_CHANGED, undefined, @@ -136,7 +136,7 @@ describe('Firebase Storage > Upload Task', () => { new Reference(storageService, testLocation), smallBlob ); - return new Promise(resolve => { + return new Promise(resolve => { task.on(TaskEvent.STATE_CHANGED, { error: () => { assert.fail('Unexpected upload failure');