UNPKG

@angular/fire

Version:
250 lines (241 loc) 12.8 kB
import { pendingUntilEvent } from '@angular/core/rxjs-interop'; import * as i1 from '@angular/fire'; import { ɵAngularFireSchedulers as _AngularFireSchedulers, VERSION } from '@angular/fire'; import { Observable, of, from } from 'rxjs'; import { debounceTime, map, observeOn, switchMap, tap } from 'rxjs/operators'; import * as i0 from '@angular/core'; import { InjectionToken, inject, EnvironmentInjector, PLATFORM_ID, Injectable, Inject, Optional, makeStateKey, Pipe, NgModule } from '@angular/core'; import * as i2 from '@angular/fire/app-check'; import { ɵfirebaseAppFactory as _firebaseAppFactory, ɵcacheInstance as _cacheInstance, FIREBASE_OPTIONS, FIREBASE_APP_NAME } from '@angular/fire/compat'; import 'firebase/compat/storage'; import firebase from 'firebase/compat/app'; import { AsyncPipe } from '@angular/common'; // need to import, else the types become import('firebase/compat/app').default.storage.UploadTask // and it no longer works w/Firebase v7 // Things aren't working great, I'm having to put in a lot of work-arounds for what // appear to be Firebase JS SDK bugs https://github.com/firebase/firebase-js-sdk/issues/4158 function fromTask(task) { return new Observable(subscriber => { const progress = (snap) => subscriber.next(snap); const error = e => subscriber.error(e); const complete = () => subscriber.complete(); // emit the current snapshot, so they don't have to wait for state_changes // to fire next... this is stale if the task is no longer running :( progress(task.snapshot); const unsub = task.on('state_changed', progress); // it turns out that neither task snapshot nor 'state_changed' fire the last // snapshot before completion, the one with status 'success" and 100% progress // so let's use the promise form of the task for that task.then(snapshot => { progress(snapshot); complete(); }, e => { // TODO investigate, again this is stale, we never fire a canceled or error it seems progress(task.snapshot); error(e); }); // on's type if Function, rather than () => void, need to wrap return function unsubscribe() { unsub(); }; }).pipe( // deal with sync emissions from first emitting `task.snapshot`, this makes sure // that if the task is already finished we don't emit the old running state debounceTime(0)); } /** * Create an AngularFireUploadTask from a regular UploadTask from the Storage SDK. * This method creates an observable of the upload and returns on object that provides * multiple methods for controlling and monitoring the file upload. */ function createUploadTask(task) { const inner$ = fromTask(task); return { task, then: task.then.bind(task), catch: task.catch.bind(task), pause: task.pause.bind(task), cancel: task.cancel.bind(task), resume: task.resume.bind(task), snapshotChanges: () => inner$, percentageChanges: () => inner$.pipe(map(s => s.bytesTransferred / s.totalBytes * 100)) }; } /** * Create an AngularFire wrapped Storage Reference. This object * creates observable methods from promise based methods. */ function createStorageRef(ref, injector) { return { getDownloadURL: () => of(undefined).pipe(observeOn(injector.get(_AngularFireSchedulers).outsideAngular), switchMap(() => ref.getDownloadURL()), pendingUntilEvent(injector)), getMetadata: () => of(undefined).pipe(observeOn(injector.get(_AngularFireSchedulers).outsideAngular), switchMap(() => ref.getMetadata()), pendingUntilEvent(injector)), delete: () => from(ref.delete()), child: (path) => createStorageRef(ref.child(path), injector), updateMetadata: (meta) => from(ref.updateMetadata(meta)), put: (data, metadata) => { const task = ref.put(data, metadata); return createUploadTask(task); }, putString: (data, format, metadata) => { const task = ref.putString(data, format, metadata); return createUploadTask(task); }, list: (options) => from(ref.list(options)), listAll: () => from(ref.listAll()) }; } const BUCKET = new InjectionToken('angularfire2.storageBucket'); const MAX_UPLOAD_RETRY_TIME = new InjectionToken('angularfire2.storage.maxUploadRetryTime'); const MAX_OPERATION_RETRY_TIME = new InjectionToken('angularfire2.storage.maxOperationRetryTime'); const USE_EMULATOR = new InjectionToken('angularfire2.storage.use-emulator'); /** * AngularFireStorage Service * * This service is the main entry point for this feature module. It provides * an API for uploading and downloading binary files from Cloud Storage for * Firebase. */ class AngularFireStorage { storage; injector = inject(EnvironmentInjector); constructor(options, name, storageBucket, // eslint-disable-next-line @typescript-eslint/ban-types platformId, zone, schedulers, maxUploadRetryTime, maxOperationRetryTime, _useEmulator, _appCheckInstances) { const app = _firebaseAppFactory(options, zone, name); this.storage = _cacheInstance(`${app.name}.storage.${storageBucket}`, 'AngularFireStorage', app.name, () => { const storage = zone.runOutsideAngular(() => app.storage(storageBucket || undefined)); const useEmulator = _useEmulator; if (useEmulator) { storage.useEmulator(...useEmulator); } if (maxUploadRetryTime) { storage.setMaxUploadRetryTime(maxUploadRetryTime); } if (maxOperationRetryTime) { storage.setMaxOperationRetryTime(maxOperationRetryTime); } return storage; }, [maxUploadRetryTime, maxOperationRetryTime]); } ref(path) { return createStorageRef(this.storage.ref(path), this.injector); } refFromURL(path) { return createStorageRef(this.storage.refFromURL(path), this.injector); } upload(path, data, metadata) { const storageRef = this.storage.ref(path); const ref = createStorageRef(storageRef, this.injector); return ref.put(data, metadata); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: AngularFireStorage, deps: [{ token: FIREBASE_OPTIONS }, { token: FIREBASE_APP_NAME, optional: true }, { token: BUCKET, optional: true }, { token: PLATFORM_ID }, { token: i0.NgZone }, { token: i1.ɵAngularFireSchedulers }, { token: MAX_UPLOAD_RETRY_TIME, optional: true }, { token: MAX_OPERATION_RETRY_TIME, optional: true }, { token: USE_EMULATOR, optional: true }, { token: i2.AppCheckInstances, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: AngularFireStorage, providedIn: 'any' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: AngularFireStorage, decorators: [{ type: Injectable, args: [{ providedIn: 'any' }] }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Inject, args: [FIREBASE_OPTIONS] }] }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [FIREBASE_APP_NAME] }] }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [BUCKET] }] }, { type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID] }] }, { type: i0.NgZone }, { type: i1.ɵAngularFireSchedulers }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [MAX_UPLOAD_RETRY_TIME] }] }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [MAX_OPERATION_RETRY_TIME] }] }, { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [USE_EMULATOR] }] }, { type: i2.AppCheckInstances, decorators: [{ type: Optional }] }] }); /** to be used with in combination with | async */ class GetDownloadURLPipe { storage; state; asyncPipe; path; downloadUrl$; constructor(storage, cdr, state) { this.storage = storage; this.state = state; this.asyncPipe = new AsyncPipe(cdr); } transform(path) { if (path !== this.path) { this.path = path; const key = makeStateKey(`|getDownloadURL|${path}`); const existing = this.state?.get(key, undefined); this.downloadUrl$ = existing ? of(existing) : this.storage.ref(path).getDownloadURL().pipe(tap(it => this.state?.set(key, it))); } return this.asyncPipe.transform(this.downloadUrl$); } ngOnDestroy() { this.asyncPipe.ngOnDestroy(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: GetDownloadURLPipe, deps: [{ token: AngularFireStorage }, { token: i0.ChangeDetectorRef }, { token: i0.TransferState, optional: true }], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.0", ngImport: i0, type: GetDownloadURLPipe, isStandalone: true, name: "getDownloadURL", pure: false }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: GetDownloadURLPipe, decorators: [{ type: Pipe, args: [{ name: 'getDownloadURL', pure: false, }] }], ctorParameters: () => [{ type: AngularFireStorage }, { type: i0.ChangeDetectorRef }, { type: i0.TransferState, decorators: [{ type: Optional }] }] }); class GetDownloadURLPipeModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: GetDownloadURLPipeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.0", ngImport: i0, type: GetDownloadURLPipeModule, imports: [GetDownloadURLPipe], exports: [GetDownloadURLPipe] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: GetDownloadURLPipeModule }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: GetDownloadURLPipeModule, decorators: [{ type: NgModule, args: [{ imports: [GetDownloadURLPipe], exports: [GetDownloadURLPipe], }] }] }); class AngularFireStorageModule { constructor() { firebase.registerVersion('angularfire', VERSION.full, 'gcs-compat'); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: AngularFireStorageModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.0", ngImport: i0, type: AngularFireStorageModule, imports: [GetDownloadURLPipeModule], exports: [GetDownloadURLPipeModule] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: AngularFireStorageModule, providers: [AngularFireStorage], imports: [GetDownloadURLPipeModule, GetDownloadURLPipeModule] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: AngularFireStorageModule, decorators: [{ type: NgModule, args: [{ imports: [GetDownloadURLPipeModule], exports: [GetDownloadURLPipeModule], providers: [AngularFireStorage] }] }], ctorParameters: () => [] }); /** * Generated bundle index. Do not edit. */ export { AngularFireStorage, AngularFireStorageModule, BUCKET, GetDownloadURLPipe, GetDownloadURLPipeModule, MAX_OPERATION_RETRY_TIME, MAX_UPLOAD_RETRY_TIME, USE_EMULATOR, createStorageRef, createUploadTask, fromTask }; //# sourceMappingURL=angular-fire-compat-storage.mjs.map