No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.esm5.js 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. import { __values, __read, __awaiter, __generator, __spreadArray } from 'tslib';
  2. import { Deferred } from '@firebase/util';
  3. /**
  4. * Component for service name T, e.g. `auth`, `auth-internal`
  5. */
  6. var Component = /** @class */ (function () {
  7. /**
  8. *
  9. * @param name The public service name, e.g. app, auth, firestore, database
  10. * @param instanceFactory Service factory responsible for creating the public interface
  11. * @param type whether the service provided by the component is public or private
  12. */
  13. function Component(name, instanceFactory, type) {
  14. this.name = name;
  15. this.instanceFactory = instanceFactory;
  16. this.type = type;
  17. this.multipleInstances = false;
  18. /**
  19. * Properties to be added to the service namespace
  20. */
  21. this.serviceProps = {};
  22. this.instantiationMode = "LAZY" /* InstantiationMode.LAZY */;
  23. this.onInstanceCreated = null;
  24. }
  25. Component.prototype.setInstantiationMode = function (mode) {
  26. this.instantiationMode = mode;
  27. return this;
  28. };
  29. Component.prototype.setMultipleInstances = function (multipleInstances) {
  30. this.multipleInstances = multipleInstances;
  31. return this;
  32. };
  33. Component.prototype.setServiceProps = function (props) {
  34. this.serviceProps = props;
  35. return this;
  36. };
  37. Component.prototype.setInstanceCreatedCallback = function (callback) {
  38. this.onInstanceCreated = callback;
  39. return this;
  40. };
  41. return Component;
  42. }());
  43. /**
  44. * @license
  45. * Copyright 2019 Google LLC
  46. *
  47. * Licensed under the Apache License, Version 2.0 (the "License");
  48. * you may not use this file except in compliance with the License.
  49. * You may obtain a copy of the License at
  50. *
  51. * http://www.apache.org/licenses/LICENSE-2.0
  52. *
  53. * Unless required by applicable law or agreed to in writing, software
  54. * distributed under the License is distributed on an "AS IS" BASIS,
  55. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  56. * See the License for the specific language governing permissions and
  57. * limitations under the License.
  58. */
  59. var DEFAULT_ENTRY_NAME = '[DEFAULT]';
  60. /**
  61. * @license
  62. * Copyright 2019 Google LLC
  63. *
  64. * Licensed under the Apache License, Version 2.0 (the "License");
  65. * you may not use this file except in compliance with the License.
  66. * You may obtain a copy of the License at
  67. *
  68. * http://www.apache.org/licenses/LICENSE-2.0
  69. *
  70. * Unless required by applicable law or agreed to in writing, software
  71. * distributed under the License is distributed on an "AS IS" BASIS,
  72. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  73. * See the License for the specific language governing permissions and
  74. * limitations under the License.
  75. */
  76. /**
  77. * Provider for instance for service name T, e.g. 'auth', 'auth-internal'
  78. * NameServiceMapping[T] is an alias for the type of the instance
  79. */
  80. var Provider = /** @class */ (function () {
  81. function Provider(name, container) {
  82. this.name = name;
  83. this.container = container;
  84. this.component = null;
  85. this.instances = new Map();
  86. this.instancesDeferred = new Map();
  87. this.instancesOptions = new Map();
  88. this.onInitCallbacks = new Map();
  89. }
  90. /**
  91. * @param identifier A provider can provide mulitple instances of a service
  92. * if this.component.multipleInstances is true.
  93. */
  94. Provider.prototype.get = function (identifier) {
  95. // if multipleInstances is not supported, use the default name
  96. var normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
  97. if (!this.instancesDeferred.has(normalizedIdentifier)) {
  98. var deferred = new Deferred();
  99. this.instancesDeferred.set(normalizedIdentifier, deferred);
  100. if (this.isInitialized(normalizedIdentifier) ||
  101. this.shouldAutoInitialize()) {
  102. // initialize the service if it can be auto-initialized
  103. try {
  104. var instance = this.getOrInitializeService({
  105. instanceIdentifier: normalizedIdentifier
  106. });
  107. if (instance) {
  108. deferred.resolve(instance);
  109. }
  110. }
  111. catch (e) {
  112. // when the instance factory throws an exception during get(), it should not cause
  113. // a fatal error. We just return the unresolved promise in this case.
  114. }
  115. }
  116. }
  117. return this.instancesDeferred.get(normalizedIdentifier).promise;
  118. };
  119. Provider.prototype.getImmediate = function (options) {
  120. var _a;
  121. // if multipleInstances is not supported, use the default name
  122. var normalizedIdentifier = this.normalizeInstanceIdentifier(options === null || options === void 0 ? void 0 : options.identifier);
  123. var optional = (_a = options === null || options === void 0 ? void 0 : options.optional) !== null && _a !== void 0 ? _a : false;
  124. if (this.isInitialized(normalizedIdentifier) ||
  125. this.shouldAutoInitialize()) {
  126. try {
  127. return this.getOrInitializeService({
  128. instanceIdentifier: normalizedIdentifier
  129. });
  130. }
  131. catch (e) {
  132. if (optional) {
  133. return null;
  134. }
  135. else {
  136. throw e;
  137. }
  138. }
  139. }
  140. else {
  141. // In case a component is not initialized and should/can not be auto-initialized at the moment, return null if the optional flag is set, or throw
  142. if (optional) {
  143. return null;
  144. }
  145. else {
  146. throw Error("Service ".concat(this.name, " is not available"));
  147. }
  148. }
  149. };
  150. Provider.prototype.getComponent = function () {
  151. return this.component;
  152. };
  153. Provider.prototype.setComponent = function (component) {
  154. var e_1, _a;
  155. if (component.name !== this.name) {
  156. throw Error("Mismatching Component ".concat(component.name, " for Provider ").concat(this.name, "."));
  157. }
  158. if (this.component) {
  159. throw Error("Component for ".concat(this.name, " has already been provided"));
  160. }
  161. this.component = component;
  162. // return early without attempting to initialize the component if the component requires explicit initialization (calling `Provider.initialize()`)
  163. if (!this.shouldAutoInitialize()) {
  164. return;
  165. }
  166. // if the service is eager, initialize the default instance
  167. if (isComponentEager(component)) {
  168. try {
  169. this.getOrInitializeService({ instanceIdentifier: DEFAULT_ENTRY_NAME });
  170. }
  171. catch (e) {
  172. // when the instance factory for an eager Component throws an exception during the eager
  173. // initialization, it should not cause a fatal error.
  174. // TODO: Investigate if we need to make it configurable, because some component may want to cause
  175. // a fatal error in this case?
  176. }
  177. }
  178. try {
  179. // Create service instances for the pending promises and resolve them
  180. // NOTE: if this.multipleInstances is false, only the default instance will be created
  181. // and all promises with resolve with it regardless of the identifier.
  182. for (var _b = __values(this.instancesDeferred.entries()), _c = _b.next(); !_c.done; _c = _b.next()) {
  183. var _d = __read(_c.value, 2), instanceIdentifier = _d[0], instanceDeferred = _d[1];
  184. var normalizedIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
  185. try {
  186. // `getOrInitializeService()` should always return a valid instance since a component is guaranteed. use ! to make typescript happy.
  187. var instance = this.getOrInitializeService({
  188. instanceIdentifier: normalizedIdentifier
  189. });
  190. instanceDeferred.resolve(instance);
  191. }
  192. catch (e) {
  193. // when the instance factory throws an exception, it should not cause
  194. // a fatal error. We just leave the promise unresolved.
  195. }
  196. }
  197. }
  198. catch (e_1_1) { e_1 = { error: e_1_1 }; }
  199. finally {
  200. try {
  201. if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
  202. }
  203. finally { if (e_1) throw e_1.error; }
  204. }
  205. };
  206. Provider.prototype.clearInstance = function (identifier) {
  207. if (identifier === void 0) { identifier = DEFAULT_ENTRY_NAME; }
  208. this.instancesDeferred.delete(identifier);
  209. this.instancesOptions.delete(identifier);
  210. this.instances.delete(identifier);
  211. };
  212. // app.delete() will call this method on every provider to delete the services
  213. // TODO: should we mark the provider as deleted?
  214. Provider.prototype.delete = function () {
  215. return __awaiter(this, void 0, void 0, function () {
  216. var services;
  217. return __generator(this, function (_a) {
  218. switch (_a.label) {
  219. case 0:
  220. services = Array.from(this.instances.values());
  221. return [4 /*yield*/, Promise.all(__spreadArray(__spreadArray([], __read(services
  222. .filter(function (service) { return 'INTERNAL' in service; }) // legacy services
  223. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  224. .map(function (service) { return service.INTERNAL.delete(); })), false), __read(services
  225. .filter(function (service) { return '_delete' in service; }) // modularized services
  226. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  227. .map(function (service) { return service._delete(); })), false))];
  228. case 1:
  229. _a.sent();
  230. return [2 /*return*/];
  231. }
  232. });
  233. });
  234. };
  235. Provider.prototype.isComponentSet = function () {
  236. return this.component != null;
  237. };
  238. Provider.prototype.isInitialized = function (identifier) {
  239. if (identifier === void 0) { identifier = DEFAULT_ENTRY_NAME; }
  240. return this.instances.has(identifier);
  241. };
  242. Provider.prototype.getOptions = function (identifier) {
  243. if (identifier === void 0) { identifier = DEFAULT_ENTRY_NAME; }
  244. return this.instancesOptions.get(identifier) || {};
  245. };
  246. Provider.prototype.initialize = function (opts) {
  247. var e_2, _a;
  248. if (opts === void 0) { opts = {}; }
  249. var _b = opts.options, options = _b === void 0 ? {} : _b;
  250. var normalizedIdentifier = this.normalizeInstanceIdentifier(opts.instanceIdentifier);
  251. if (this.isInitialized(normalizedIdentifier)) {
  252. throw Error("".concat(this.name, "(").concat(normalizedIdentifier, ") has already been initialized"));
  253. }
  254. if (!this.isComponentSet()) {
  255. throw Error("Component ".concat(this.name, " has not been registered yet"));
  256. }
  257. var instance = this.getOrInitializeService({
  258. instanceIdentifier: normalizedIdentifier,
  259. options: options
  260. });
  261. try {
  262. // resolve any pending promise waiting for the service instance
  263. for (var _c = __values(this.instancesDeferred.entries()), _d = _c.next(); !_d.done; _d = _c.next()) {
  264. var _e = __read(_d.value, 2), instanceIdentifier = _e[0], instanceDeferred = _e[1];
  265. var normalizedDeferredIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
  266. if (normalizedIdentifier === normalizedDeferredIdentifier) {
  267. instanceDeferred.resolve(instance);
  268. }
  269. }
  270. }
  271. catch (e_2_1) { e_2 = { error: e_2_1 }; }
  272. finally {
  273. try {
  274. if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
  275. }
  276. finally { if (e_2) throw e_2.error; }
  277. }
  278. return instance;
  279. };
  280. /**
  281. *
  282. * @param callback - a function that will be invoked after the provider has been initialized by calling provider.initialize().
  283. * The function is invoked SYNCHRONOUSLY, so it should not execute any longrunning tasks in order to not block the program.
  284. *
  285. * @param identifier An optional instance identifier
  286. * @returns a function to unregister the callback
  287. */
  288. Provider.prototype.onInit = function (callback, identifier) {
  289. var _a;
  290. var normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
  291. var existingCallbacks = (_a = this.onInitCallbacks.get(normalizedIdentifier)) !== null && _a !== void 0 ? _a : new Set();
  292. existingCallbacks.add(callback);
  293. this.onInitCallbacks.set(normalizedIdentifier, existingCallbacks);
  294. var existingInstance = this.instances.get(normalizedIdentifier);
  295. if (existingInstance) {
  296. callback(existingInstance, normalizedIdentifier);
  297. }
  298. return function () {
  299. existingCallbacks.delete(callback);
  300. };
  301. };
  302. /**
  303. * Invoke onInit callbacks synchronously
  304. * @param instance the service instance`
  305. */
  306. Provider.prototype.invokeOnInitCallbacks = function (instance, identifier) {
  307. var e_3, _a;
  308. var callbacks = this.onInitCallbacks.get(identifier);
  309. if (!callbacks) {
  310. return;
  311. }
  312. try {
  313. for (var callbacks_1 = __values(callbacks), callbacks_1_1 = callbacks_1.next(); !callbacks_1_1.done; callbacks_1_1 = callbacks_1.next()) {
  314. var callback = callbacks_1_1.value;
  315. try {
  316. callback(instance, identifier);
  317. }
  318. catch (_b) {
  319. // ignore errors in the onInit callback
  320. }
  321. }
  322. }
  323. catch (e_3_1) { e_3 = { error: e_3_1 }; }
  324. finally {
  325. try {
  326. if (callbacks_1_1 && !callbacks_1_1.done && (_a = callbacks_1.return)) _a.call(callbacks_1);
  327. }
  328. finally { if (e_3) throw e_3.error; }
  329. }
  330. };
  331. Provider.prototype.getOrInitializeService = function (_a) {
  332. var instanceIdentifier = _a.instanceIdentifier, _b = _a.options, options = _b === void 0 ? {} : _b;
  333. var instance = this.instances.get(instanceIdentifier);
  334. if (!instance && this.component) {
  335. instance = this.component.instanceFactory(this.container, {
  336. instanceIdentifier: normalizeIdentifierForFactory(instanceIdentifier),
  337. options: options
  338. });
  339. this.instances.set(instanceIdentifier, instance);
  340. this.instancesOptions.set(instanceIdentifier, options);
  341. /**
  342. * Invoke onInit listeners.
  343. * Note this.component.onInstanceCreated is different, which is used by the component creator,
  344. * while onInit listeners are registered by consumers of the provider.
  345. */
  346. this.invokeOnInitCallbacks(instance, instanceIdentifier);
  347. /**
  348. * Order is important
  349. * onInstanceCreated() should be called after this.instances.set(instanceIdentifier, instance); which
  350. * makes `isInitialized()` return true.
  351. */
  352. if (this.component.onInstanceCreated) {
  353. try {
  354. this.component.onInstanceCreated(this.container, instanceIdentifier, instance);
  355. }
  356. catch (_c) {
  357. // ignore errors in the onInstanceCreatedCallback
  358. }
  359. }
  360. }
  361. return instance || null;
  362. };
  363. Provider.prototype.normalizeInstanceIdentifier = function (identifier) {
  364. if (identifier === void 0) { identifier = DEFAULT_ENTRY_NAME; }
  365. if (this.component) {
  366. return this.component.multipleInstances ? identifier : DEFAULT_ENTRY_NAME;
  367. }
  368. else {
  369. return identifier; // assume multiple instances are supported before the component is provided.
  370. }
  371. };
  372. Provider.prototype.shouldAutoInitialize = function () {
  373. return (!!this.component &&
  374. this.component.instantiationMode !== "EXPLICIT" /* InstantiationMode.EXPLICIT */);
  375. };
  376. return Provider;
  377. }());
  378. // undefined should be passed to the service factory for the default instance
  379. function normalizeIdentifierForFactory(identifier) {
  380. return identifier === DEFAULT_ENTRY_NAME ? undefined : identifier;
  381. }
  382. function isComponentEager(component) {
  383. return component.instantiationMode === "EAGER" /* InstantiationMode.EAGER */;
  384. }
  385. /**
  386. * @license
  387. * Copyright 2019 Google LLC
  388. *
  389. * Licensed under the Apache License, Version 2.0 (the "License");
  390. * you may not use this file except in compliance with the License.
  391. * You may obtain a copy of the License at
  392. *
  393. * http://www.apache.org/licenses/LICENSE-2.0
  394. *
  395. * Unless required by applicable law or agreed to in writing, software
  396. * distributed under the License is distributed on an "AS IS" BASIS,
  397. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  398. * See the License for the specific language governing permissions and
  399. * limitations under the License.
  400. */
  401. /**
  402. * ComponentContainer that provides Providers for service name T, e.g. `auth`, `auth-internal`
  403. */
  404. var ComponentContainer = /** @class */ (function () {
  405. function ComponentContainer(name) {
  406. this.name = name;
  407. this.providers = new Map();
  408. }
  409. /**
  410. *
  411. * @param component Component being added
  412. * @param overwrite When a component with the same name has already been registered,
  413. * if overwrite is true: overwrite the existing component with the new component and create a new
  414. * provider with the new component. It can be useful in tests where you want to use different mocks
  415. * for different tests.
  416. * if overwrite is false: throw an exception
  417. */
  418. ComponentContainer.prototype.addComponent = function (component) {
  419. var provider = this.getProvider(component.name);
  420. if (provider.isComponentSet()) {
  421. throw new Error("Component ".concat(component.name, " has already been registered with ").concat(this.name));
  422. }
  423. provider.setComponent(component);
  424. };
  425. ComponentContainer.prototype.addOrOverwriteComponent = function (component) {
  426. var provider = this.getProvider(component.name);
  427. if (provider.isComponentSet()) {
  428. // delete the existing provider from the container, so we can register the new component
  429. this.providers.delete(component.name);
  430. }
  431. this.addComponent(component);
  432. };
  433. /**
  434. * getProvider provides a type safe interface where it can only be called with a field name
  435. * present in NameServiceMapping interface.
  436. *
  437. * Firebase SDKs providing services should extend NameServiceMapping interface to register
  438. * themselves.
  439. */
  440. ComponentContainer.prototype.getProvider = function (name) {
  441. if (this.providers.has(name)) {
  442. return this.providers.get(name);
  443. }
  444. // create a Provider for a service that hasn't registered with Firebase
  445. var provider = new Provider(name, this);
  446. this.providers.set(name, provider);
  447. return provider;
  448. };
  449. ComponentContainer.prototype.getProviders = function () {
  450. return Array.from(this.providers.values());
  451. };
  452. return ComponentContainer;
  453. }());
  454. export { Component, ComponentContainer, Provider };
  455. //# sourceMappingURL=index.esm5.js.map