UNPKG

12.4 kBJavaScriptView Raw
1import * as i0 from '@angular/core';
2import { Version, Injectable } from '@angular/core';
3import { getApps } from 'firebase/app';
4import { isSupported as isSupported$2 } from 'firebase/remote-config';
5import { isSupported as isSupported$1 } from 'firebase/messaging';
6import { isSupported } from 'firebase/analytics';
7import { queueScheduler, asyncScheduler, Observable } from 'rxjs';
8import { tap, observeOn, subscribeOn } from 'rxjs/operators';
9
10const VERSION = new Version('7.3.0');
11const isAnalyticsSupportedValueSymbol = '__angularfire_symbol__analyticsIsSupportedValue';
12const isAnalyticsSupportedPromiseSymbol = '__angularfire_symbol__analyticsIsSupported';
13const isRemoteConfigSupportedValueSymbol = '__angularfire_symbol__remoteConfigIsSupportedValue';
14const isRemoteConfigSupportedPromiseSymbol = '__angularfire_symbol__remoteConfigIsSupported';
15const isMessagingSupportedValueSymbol = '__angularfire_symbol__messagingIsSupportedValue';
16const isMessagingSupportedPromiseSymbol = '__angularfire_symbol__messagingIsSupported';
17globalThis[isAnalyticsSupportedPromiseSymbol] || (globalThis[isAnalyticsSupportedPromiseSymbol] = isSupported().then(it => globalThis[isAnalyticsSupportedValueSymbol] = it).catch(() => globalThis[isAnalyticsSupportedValueSymbol] = false));
18globalThis[isMessagingSupportedPromiseSymbol] || (globalThis[isMessagingSupportedPromiseSymbol] = isSupported$1().then(it => globalThis[isMessagingSupportedValueSymbol] = it).catch(() => globalThis[isMessagingSupportedValueSymbol] = false));
19globalThis[isRemoteConfigSupportedPromiseSymbol] || (globalThis[isRemoteConfigSupportedPromiseSymbol] = isSupported$2().then(it => globalThis[isRemoteConfigSupportedValueSymbol] = it).catch(() => globalThis[isRemoteConfigSupportedValueSymbol] = false));
20const isSupportedError = (module) => `The APP_INITIALIZER that is "making" isSupported() sync for the sake of convenient DI has not resolved in this
21context. Rather than injecting ${module} in the constructor, first ensure that ${module} is supported by calling
22\`await isSupported()\`, then retrieve the instance from the injector manually \`injector.get(${module})\`.`;
23const ɵisMessagingSupportedFactory = {
24 async: () => globalThis[isMessagingSupportedPromiseSymbol],
25 sync: () => {
26 const ret = globalThis[isMessagingSupportedValueSymbol];
27 if (ret === undefined) {
28 throw new Error(isSupportedError('Messaging'));
29 }
30 return ret;
31 }
32};
33const ɵisRemoteConfigSupportedFactory = {
34 async: () => globalThis[isRemoteConfigSupportedPromiseSymbol],
35 sync: () => {
36 const ret = globalThis[isRemoteConfigSupportedValueSymbol];
37 if (ret === undefined) {
38 throw new Error(isSupportedError('RemoteConfig'));
39 }
40 return ret;
41 }
42};
43const ɵisAnalyticsSupportedFactory = {
44 async: () => globalThis[isAnalyticsSupportedPromiseSymbol],
45 sync: () => {
46 const ret = globalThis[isAnalyticsSupportedValueSymbol];
47 if (ret === undefined) {
48 throw new Error(isSupportedError('Analytics'));
49 }
50 return ret;
51 }
52};
53function ɵgetDefaultInstanceOf(identifier, provided, defaultApp) {
54 if (provided) {
55 // Was provide* only called once? If so grab that
56 if (provided.length === 1) {
57 return provided[0];
58 }
59 const providedUsingDefaultApp = provided.filter((it) => it.app === defaultApp);
60 // Was provide* only called once, using the default app? If so use that
61 if (providedUsingDefaultApp.length === 1) {
62 return providedUsingDefaultApp[0];
63 }
64 }
65 // Grab the default instance from the defaultApp
66 const defaultAppWithContainer = defaultApp;
67 const provider = defaultAppWithContainer.container.getProvider(identifier);
68 return provider.getImmediate({ optional: true });
69}
70const ɵgetAllInstancesOf = (identifier, app) => {
71 const apps = app ? [app] : getApps();
72 const instances = [];
73 apps.forEach((app) => {
74 const provider = app.container.getProvider(identifier);
75 provider.instances.forEach((instance) => {
76 if (!instances.includes(instance)) {
77 instances.push(instance);
78 }
79 });
80 });
81 return instances;
82};
83
84function noop() {
85}
86/**
87 * Schedules tasks so that they are invoked inside the Zone that is passed in the constructor.
88 */
89// tslint:disable-next-line:class-name
90class ɵZoneScheduler {
91 constructor(zone, delegate = queueScheduler) {
92 this.zone = zone;
93 this.delegate = delegate;
94 }
95 now() {
96 return this.delegate.now();
97 }
98 schedule(work, delay, state) {
99 const targetZone = this.zone;
100 // Wrap the specified work function to make sure that if nested scheduling takes place the
101 // work is executed in the correct zone
102 const workInZone = function (state) {
103 targetZone.runGuarded(() => {
104 work.apply(this, [state]);
105 });
106 };
107 // Scheduling itself needs to be run in zone to ensure setInterval calls for async scheduling are done
108 // inside the correct zone. This scheduler needs to schedule asynchronously always to ensure that
109 // firebase emissions are never synchronous. Specifying a delay causes issues with the queueScheduler delegate.
110 return this.delegate.schedule(workInZone, delay, state);
111 }
112}
113class BlockUntilFirstOperator {
114 constructor(zone) {
115 this.zone = zone;
116 this.task = null;
117 }
118 call(subscriber, source) {
119 const unscheduleTask = this.unscheduleTask.bind(this);
120 this.task = this.zone.run(() => Zone.current.scheduleMacroTask('firebaseZoneBlock', noop, {}, noop, noop));
121 return source.pipe(tap({ next: unscheduleTask, complete: unscheduleTask, error: unscheduleTask })).subscribe(subscriber).add(unscheduleTask);
122 }
123 unscheduleTask() {
124 // maybe this is a race condition, invoke in a timeout
125 // hold for 10ms while I try to figure out what is going on
126 setTimeout(() => {
127 if (this.task != null && this.task.state === 'scheduled') {
128 this.task.invoke();
129 this.task = null;
130 }
131 }, 10);
132 }
133}
134// tslint:disable-next-line:class-name
135class ɵAngularFireSchedulers {
136 constructor(ngZone) {
137 this.ngZone = ngZone;
138 this.outsideAngular = ngZone.runOutsideAngular(() => new ɵZoneScheduler(Zone.current));
139 this.insideAngular = ngZone.run(() => new ɵZoneScheduler(Zone.current, asyncScheduler));
140 globalThis.ɵAngularFireScheduler || (globalThis.ɵAngularFireScheduler = this);
141 }
142}
143ɵAngularFireSchedulers.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.3", ngImport: i0, type: ɵAngularFireSchedulers, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
144ɵAngularFireSchedulers.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.1.3", ngImport: i0, type: ɵAngularFireSchedulers, providedIn: 'root' });
145i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.3", ngImport: i0, type: ɵAngularFireSchedulers, decorators: [{
146 type: Injectable,
147 args: [{
148 providedIn: 'root',
149 }]
150 }], ctorParameters: function () { return [{ type: i0.NgZone }]; } });
151function getSchedulers() {
152 const schedulers = globalThis.ɵAngularFireScheduler;
153 if (!schedulers) {
154 throw new Error(`Either AngularFireModule has not been provided in your AppModule (this can be done manually or implictly using
155provideFirebaseApp) or you're calling an AngularFire method outside of an NgModule (which is not supported).`);
156 }
157 return schedulers;
158}
159function runOutsideAngular(fn) {
160 return getSchedulers().ngZone.runOutsideAngular(() => fn());
161}
162function run(fn) {
163 return getSchedulers().ngZone.run(() => fn());
164}
165function observeOutsideAngular(obs$) {
166 return obs$.pipe(observeOn(getSchedulers().outsideAngular));
167}
168function observeInsideAngular(obs$) {
169 return obs$.pipe(observeOn(getSchedulers().insideAngular));
170}
171function keepUnstableUntilFirst(obs$) {
172 const scheduler = getSchedulers();
173 return ɵkeepUnstableUntilFirstFactory(getSchedulers())(obs$);
174}
175/**
176 * Operator to block the zone until the first value has been emitted or the observable
177 * has completed/errored. This is used to make sure that universal waits until the first
178 * value from firebase but doesn't block the zone forever since the firebase subscription
179 * is still alive.
180 */
181function ɵkeepUnstableUntilFirstFactory(schedulers) {
182 return function keepUnstableUntilFirst(obs$) {
183 obs$ = obs$.lift(new BlockUntilFirstOperator(schedulers.ngZone));
184 return obs$.pipe(
185 // Run the subscribe body outside of Angular (e.g. calling Firebase SDK to add a listener to a change event)
186 subscribeOn(schedulers.outsideAngular),
187 // Run operators inside the angular zone (e.g. side effects via tap())
188 observeOn(schedulers.insideAngular)
189 // INVESTIGATE https://github.com/angular/angularfire/pull/2315
190 // share()
191 );
192 };
193}
194const zoneWrapFn = (it, macrotask) => {
195 const _this = this;
196 // function() is needed for the arguments object
197 // tslint:disable-next-line:only-arrow-functions
198 return function () {
199 const _arguments = arguments;
200 if (macrotask) {
201 setTimeout(() => {
202 if (macrotask.state === 'scheduled') {
203 macrotask.invoke();
204 }
205 }, 10);
206 }
207 return run(() => it.apply(_this, _arguments));
208 };
209};
210const ɵzoneWrap = (it, blockUntilFirst) => {
211 // function() is needed for the arguments object
212 // tslint:disable-next-line:only-arrow-functions
213 return function () {
214 let macrotask;
215 const _arguments = arguments;
216 // if this is a callback function, e.g, onSnapshot, we should create a microtask and invoke it
217 // only once one of the callback functions is tripped.
218 for (let i = 0; i < arguments.length; i++) {
219 if (typeof _arguments[i] === 'function') {
220 if (blockUntilFirst) {
221 macrotask || (macrotask = run(() => Zone.current.scheduleMacroTask('firebaseZoneBlock', noop, {}, noop, noop)));
222 }
223 // TODO create a microtask to track callback functions
224 _arguments[i] = zoneWrapFn(_arguments[i], macrotask);
225 }
226 }
227 const ret = runOutsideAngular(() => it.apply(this, _arguments));
228 if (!blockUntilFirst) {
229 if (ret instanceof Observable) {
230 const schedulers = getSchedulers();
231 return ret.pipe(subscribeOn(schedulers.outsideAngular), observeOn(schedulers.insideAngular));
232 }
233 else {
234 return run(() => ret);
235 }
236 }
237 if (ret instanceof Observable) {
238 return ret.pipe(keepUnstableUntilFirst);
239 }
240 else if (ret instanceof Promise) {
241 return run(() => new Promise((resolve, reject) => ret.then(it => run(() => resolve(it)), reason => run(() => reject(reason)))));
242 }
243 else if (typeof ret === 'function' && macrotask) {
244 // Handle unsubscribe
245 // function() is needed for the arguments object
246 // tslint:disable-next-line:only-arrow-functions
247 return function () {
248 setTimeout(() => {
249 if (macrotask && macrotask.state === 'scheduled') {
250 macrotask.invoke();
251 }
252 }, 10);
253 return ret.apply(this, arguments);
254 };
255 }
256 else {
257 // TODO how do we handle storage uploads in Zone? and other stuff with cancel() etc?
258 return run(() => ret);
259 }
260 };
261};
262
263/**
264 * Generated bundle index. Do not edit.
265 */
266
267export { VERSION, keepUnstableUntilFirst, observeInsideAngular, observeOutsideAngular, ɵAngularFireSchedulers, ɵZoneScheduler, ɵgetAllInstancesOf, ɵgetDefaultInstanceOf, ɵisAnalyticsSupportedFactory, ɵisMessagingSupportedFactory, ɵisRemoteConfigSupportedFactory, ɵkeepUnstableUntilFirstFactory, ɵzoneWrap };
268//# sourceMappingURL=angular-fire.js.map