1 | import * as i0 from '@angular/core';
|
2 | import { InjectionToken, Injectable, Inject, Optional, NgZone, PLATFORM_ID, NgModule } from '@angular/core';
|
3 | import { pipe, of, EMPTY, concat, Observable } from 'rxjs';
|
4 | import { map, distinctUntilChanged, filter, withLatestFrom, scan, observeOn, switchMap, tap, startWith, shareReplay, groupBy, mergeMap, debounceTime } from 'rxjs/operators';
|
5 | import * as i1 from '@angular/fire';
|
6 | import { ɵAngularFireSchedulers, ɵfirebaseAppFactory, ɵfetchInstance, ɵkeepUnstableUntilFirstFactory, ɵlazySDKProxy, FIREBASE_OPTIONS, FIREBASE_APP_NAME, ɵapplyMixins } from '@angular/fire';
|
7 | import { isPlatformBrowser } from '@angular/common';
|
8 | import firebase from 'firebase/app';
|
9 |
|
10 | const proxyPolyfillCompat = {
|
11 | settings: null,
|
12 | defaultConfig: null,
|
13 | fetchTimeMillis: null,
|
14 | lastFetchStatus: null,
|
15 | activate: null,
|
16 | ensureInitialized: null,
|
17 | fetch: null,
|
18 | fetchAndActivate: null,
|
19 | getAll: null,
|
20 | getBoolean: null,
|
21 | getNumber: null,
|
22 | getString: null,
|
23 | getValue: null,
|
24 | setLogLevel: null,
|
25 | };
|
26 |
|
27 | const SETTINGS = new InjectionToken('angularfire2.remoteConfig.settings');
|
28 | const DEFAULTS = new InjectionToken('angularfire2.remoteConfig.defaultConfig');
|
29 | const AS_TO_FN = { strings: 'asString', numbers: 'asNumber', booleans: 'asBoolean' };
|
30 | const STATIC_VALUES = { numbers: 0, booleans: false, strings: undefined };
|
31 |
|
32 | const proxyAll = (observable, as) => new Proxy(observable.pipe(mapToObject(as)), {
|
33 | get: (self, name) => self[name] || observable.pipe(map(all => all.find(p => p.key === name)), map(param => param ? param[AS_TO_FN[as]]() : STATIC_VALUES[as]), distinctUntilChanged())
|
34 | });
|
35 | const ɵ0 = proxyAll;
|
36 | // TODO export as implements Partial<...> so minor doesn't break us
|
37 | class Value {
|
38 |
|
39 | constructor(_source, _value) {
|
40 | this._source = _source;
|
41 | this._value = _value;
|
42 | }
|
43 | asBoolean() {
|
44 | return ['1', 'true', 't', 'y', 'yes', 'on'].indexOf(this._value.toLowerCase()) > -1;
|
45 | }
|
46 | asString() {
|
47 | return this._value;
|
48 | }
|
49 | asNumber() {
|
50 | return Number(this._value) || 0;
|
51 | }
|
52 | getSource() {
|
53 | return this._source;
|
54 | }
|
55 | }
|
56 |
|
57 | class Parameter extends Value {
|
58 | constructor(key, fetchTimeMillis, source, value) {
|
59 | super(source, value);
|
60 | this.key = key;
|
61 | this.fetchTimeMillis = fetchTimeMillis;
|
62 | }
|
63 | }
|
64 |
|
65 | const filterTest = (fn) => filter(it => Array.isArray(it) ? it.some(fn) : fn(it));
|
66 | const ɵ1 = filterTest;
|
67 |
|
68 |
|
69 | const filterRemote = () => filterTest(p => p.getSource() === 'remote');
|
70 |
|
71 | const filterFresh = (howRecentInMillis) => filterTest(p => p.fetchTimeMillis + howRecentInMillis >= new Date().getTime());
|
72 |
|
73 |
|
74 |
|
75 |
|
76 | const scanToParametersArray = (remoteConfig) => pipe(withLatestFrom(remoteConfig), scan((existing, [all, rc]) => {
|
77 |
|
78 |
|
79 |
|
80 |
|
81 | const allKeys = [...existing.map(p => p.key), ...Object.keys(all)].filter((v, i, a) => a.indexOf(v) === i);
|
82 | return allKeys.map(key => {
|
83 | const updatedValue = all[key];
|
84 | return updatedValue ? new Parameter(key, rc ? rc.fetchTimeMillis : -1, updatedValue.getSource(), updatedValue.asString())
|
85 | : existing.find(p => p.key === key);
|
86 | });
|
87 | }, []));
|
88 | const ɵ2 = scanToParametersArray;
|
89 | class AngularFireRemoteConfig {
|
90 | constructor(options, nameOrConfig, settings, defaultConfig, zone,
|
91 | // tslint:disable-next-line:ban-types
|
92 | platformId) {
|
93 | this.zone = zone;
|
94 | const schedulers = new ɵAngularFireSchedulers(zone);
|
95 | const remoteConfig$ = of(undefined).pipe(observeOn(schedulers.outsideAngular), switchMap(() => isPlatformBrowser(platformId) ? import('firebase/remote-config') : EMPTY), switchMap(() => import('@firebase/remote-config')), tap(rc => rc.registerRemoteConfig && rc.registerRemoteConfig(firebase)), map(() => ɵfirebaseAppFactory(options, zone, nameOrConfig)), map(app => ɵfetchInstance(`${app.name}.remote-config`, 'AngularFireRemoteConfig', app, () => {
|
96 | const rc = app.remoteConfig();
|
97 | if (settings) {
|
98 | rc.settings = settings;
|
99 | }
|
100 | if (defaultConfig) {
|
101 | rc.defaultConfig = defaultConfig;
|
102 | }
|
103 | return rc;
|
104 | }, [settings, defaultConfig])),
|
105 |
|
106 | startWith(undefined), shareReplay({ bufferSize: 1, refCount: false }));
|
107 | const loadedRemoteConfig$ = remoteConfig$.pipe(filter(rc => !!rc));
|
108 | const default$ = of(Object.keys(defaultConfig || {}).reduce((c, k) => (Object.assign(Object.assign({}, c), { [k]: new Value('default', defaultConfig[k].toString()) })), {}));
|
109 |
|
110 |
|
111 | const filterOutDefaults = map(all => Object.keys(all)
|
112 | .filter(key => all[key].getSource() !== 'default')
|
113 | .reduce((acc, key) => (Object.assign(Object.assign({}, acc), { [key]: all[key] })), {}));
|
114 | const existing$ = loadedRemoteConfig$.pipe(switchMap(rc => rc.activate()
|
115 | .then(() => rc.ensureInitialized())
|
116 | .then(() => rc.getAll())), filterOutDefaults);
|
117 | const fresh$ = loadedRemoteConfig$.pipe(switchMap(rc => zone.runOutsideAngular(() => rc.fetchAndActivate()
|
118 | .then(() => rc.ensureInitialized())
|
119 | .then(() => rc.getAll()))), filterOutDefaults);
|
120 | this.parameters = concat(default$, existing$, fresh$).pipe(scanToParametersArray(remoteConfig$), ɵkeepUnstableUntilFirstFactory(schedulers), shareReplay({ bufferSize: 1, refCount: true }));
|
121 | this.changes = this.parameters.pipe(switchMap(params => of(...params)), groupBy(param => param.key), mergeMap(group => group.pipe(distinctUntilChanged())));
|
122 | this.strings = proxyAll(this.parameters, 'strings');
|
123 | this.booleans = proxyAll(this.parameters, 'booleans');
|
124 | this.numbers = proxyAll(this.parameters, 'numbers');
|
125 | return ɵlazySDKProxy(this, loadedRemoteConfig$, zone);
|
126 | }
|
127 | }
|
128 | AngularFireRemoteConfig.ɵprov = i0.ɵɵdefineInjectable({ factory: function AngularFireRemoteConfig_Factory() { return new AngularFireRemoteConfig(i0.ɵɵinject(i1.FIREBASE_OPTIONS), i0.ɵɵinject(i1.FIREBASE_APP_NAME, 8), i0.ɵɵinject(SETTINGS, 8), i0.ɵɵinject(DEFAULTS, 8), i0.ɵɵinject(i0.NgZone), i0.ɵɵinject(i0.PLATFORM_ID)); }, token: AngularFireRemoteConfig, providedIn: "any" });
|
129 | AngularFireRemoteConfig.decorators = [
|
130 | { type: Injectable, args: [{
|
131 | providedIn: 'any'
|
132 | },] }
|
133 | ];
|
134 |
|
135 | AngularFireRemoteConfig.ctorParameters = () => [
|
136 | { type: undefined, decorators: [{ type: Inject, args: [FIREBASE_OPTIONS,] }] },
|
137 | { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [FIREBASE_APP_NAME,] }] },
|
138 | { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [SETTINGS,] }] },
|
139 | { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [DEFAULTS,] }] },
|
140 | { type: NgZone },
|
141 | { type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] }
|
142 | ];
|
143 | const budget = (interval) => (source) => new Observable(observer => {
|
144 | let timedOut = false;
|
145 |
|
146 | const timeout = setTimeout(() => {
|
147 | observer.complete();
|
148 | timedOut = true;
|
149 | }, interval);
|
150 | return source.subscribe({
|
151 | next(val) {
|
152 | if (!timedOut) {
|
153 | observer.next(val);
|
154 | }
|
155 | },
|
156 | error(err) {
|
157 | if (!timedOut) {
|
158 | clearTimeout(timeout);
|
159 | observer.error(err);
|
160 | }
|
161 | },
|
162 | complete() {
|
163 | if (!timedOut) {
|
164 | clearTimeout(timeout);
|
165 | observer.complete();
|
166 | }
|
167 | }
|
168 | });
|
169 | });
|
170 | const typedMethod = (it) => {
|
171 | switch (typeof it) {
|
172 | case 'string':
|
173 | return 'asString';
|
174 | case 'boolean':
|
175 | return 'asBoolean';
|
176 | case 'number':
|
177 | return 'asNumber';
|
178 | default:
|
179 | return 'asString';
|
180 | }
|
181 | };
|
182 | const ɵ3 = typedMethod;
|
183 | function scanToObject(to = 'strings') {
|
184 | return pipe(
|
185 |
|
186 | scan((c, p) => (Object.assign(Object.assign({}, c), { [p.key]: typeof to === 'object' ?
|
187 | p[typedMethod(to[p.key])]() :
|
188 | p[AS_TO_FN[to]]() })), typeof to === 'object' ?
|
189 | to :
|
190 | {}), debounceTime(1), budget(10), distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)));
|
191 | }
|
192 | function mapToObject(to = 'strings') {
|
193 | return pipe(
|
194 |
|
195 | map((params) => params.reduce((c, p) => (Object.assign(Object.assign({}, c), { [p.key]: typeof to === 'object' ?
|
196 | p[typedMethod(to[p.key])]() :
|
197 | p[AS_TO_FN[to]]() })), typeof to === 'object' ?
|
198 | to :
|
199 | {})), distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b)));
|
200 | }
|
201 | ɵapplyMixins(AngularFireRemoteConfig, [proxyPolyfillCompat]);
|
202 |
|
203 | class AngularFireRemoteConfigModule {
|
204 | }
|
205 | AngularFireRemoteConfigModule.decorators = [
|
206 | { type: NgModule, args: [{
|
207 | providers: [AngularFireRemoteConfig]
|
208 | },] }
|
209 | ];
|
210 |
|
211 |
|
212 |
|
213 |
|
214 |
|
215 | export { AngularFireRemoteConfig, AngularFireRemoteConfigModule, DEFAULTS, Parameter, SETTINGS, Value, budget, filterFresh, filterRemote, mapToObject, scanToObject, ɵ0, ɵ1, ɵ2, ɵ3 };
|
216 |
|