暫無描述
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.

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