1 | ;
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 |
|
7 | var _namespace = require('./namespace');
|
8 |
|
9 | var _namespace2 = _interopRequireDefault(_namespace);
|
10 |
|
11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
12 |
|
13 | _namespace2.default.namespace('ima');
|
14 |
|
15 | /**
|
16 | * The Object Container is an enhanced dependency injector with support for
|
17 | * aliases and constants, and allowing to reference classes in the application
|
18 | * namespace by specifying their fully qualified names.
|
19 | */
|
20 | class ObjectContainer {
|
21 | /**
|
22 | * Returns constant for plugin binding state.
|
23 | *
|
24 | * When the object container is in plugin binding state, it is impossible
|
25 | * to register new aliases using the {@linkcode bind()} method and register
|
26 | * new constant using the {@linkcode constant()} method, or override the
|
27 | * default class dependencies of any already-configured class using the
|
28 | * {@linkcode inject()} method (classes that were not configured yet may be
|
29 | * configured using the {@linkcode inject()} method or {@linkcode provide()}
|
30 | * method).
|
31 | *
|
32 | * This prevents the unpriviledged code (e.g. 3rd party plugins) from
|
33 | * overriding the default dependency configuration provided by ima, or
|
34 | * overriding the configuration of a 3rd party plugin by another 3rd party
|
35 | * plugin.
|
36 | *
|
37 | * The application itself has always access to the unlocked object
|
38 | * container.
|
39 | *
|
40 | * @return {string} The plugin binding state.
|
41 | */
|
42 | static get PLUGIN_BINDING_STATE() {
|
43 | return 'plugin';
|
44 | }
|
45 |
|
46 | /**
|
47 | * Returns constant for IMA binding state.
|
48 | *
|
49 | * When the object container is in ima binding state, it is possible
|
50 | * to register new aliases using the {@linkcode bind()} method and register
|
51 | * new constant using the {@linkcode constant()} method, or override the
|
52 | * default class dependencies of any already-configured class using the
|
53 | * {@linkcode inject()} method (classes that were not configured yet may be
|
54 | * configured using the {@linkcode inject()} method or {@linkcode provide()}
|
55 | * method).
|
56 | *
|
57 | * @return {string} The IMA binding state.
|
58 | */
|
59 | static get IMA_BINDING_STATE() {
|
60 | return 'ima';
|
61 | }
|
62 |
|
63 | /**
|
64 | * Returns constant for app binding state.
|
65 | *
|
66 | * When the object container is in app binding state, it is possible
|
67 | * to register new aliases using the {@linkcode bind()} method and register
|
68 | * new constant using the {@linkcode constant()} method, or override the
|
69 | * default class dependencies of any already-configured class using the
|
70 | * {@linkcode inject()} method (classes that were not configured yet may be
|
71 | * configured using the {@linkcode inject()} method or {@linkcode provide()}
|
72 | * method).
|
73 | *
|
74 | * @return {string} The app binding state.
|
75 | */
|
76 | static get APP_BINDING_STATE() {
|
77 | return 'app';
|
78 | }
|
79 |
|
80 | /**
|
81 | * Initializes the object container.
|
82 | *
|
83 | * @param {ima.Namespace} namespace The namespace container, used to
|
84 | * access classes and values using their fully qualified names.
|
85 | */
|
86 | constructor(namespace) {
|
87 | /**
|
88 | * The namespace container, used to access classes and values using
|
89 | * their fully qualified names.
|
90 | *
|
91 | * @type {ima.Namespace}
|
92 | */
|
93 | this._namespace = namespace;
|
94 |
|
95 | /**
|
96 | *
|
97 | * @type {Map<(string|function(new: *, ...*)|function(...*): *), Entry<*>>}
|
98 | */
|
99 | this._entries = new Map();
|
100 |
|
101 | /**
|
102 | * The current binding state.
|
103 | *
|
104 | * The {@linkcode setBindingState()} method may be called for changing
|
105 | * object container binding state only by the bootstrap script.
|
106 | *
|
107 | * @type {?string}
|
108 | */
|
109 | this._bindingState = null;
|
110 | }
|
111 |
|
112 | /**
|
113 | * Binds the specified class or factory function and dependencies to the
|
114 | * specified alias. Binding a class or factory function to an alias allows
|
115 | * the class or function to be specied as a dependency by specifying the
|
116 | * alias and creating new instances by referring to the class or function
|
117 | * by the alias.
|
118 | *
|
119 | * Also note that the same class or function may be bound to several
|
120 | * aliases and each may use different dependencies.
|
121 | *
|
122 | * The alias will use the default dependencies bound for the class if no
|
123 | * dependencies are provided.
|
124 | *
|
125 | * @template T
|
126 | * @param {string} name Alias name.
|
127 | * @param {(function(new: T, ...*)|function(...*): T)} classConstructor The
|
128 | * class constructor or a factory function.
|
129 | * @param {?*[]} [dependencies] The dependencies to pass into the
|
130 | * constructor or factory function.
|
131 | * @return {ObjectContainer} This object container.
|
132 | */
|
133 | bind(name, classConstructor, dependencies) {
|
134 | if ($Debug) {
|
135 | if (this._bindingState === ObjectContainer.PLUGIN_BINDING_STATE) {
|
136 | throw new Error(`ima.ObjectContainer:bind Object container ` + `is locked. You do not have the permission to ` + `create a new alias named ${name}.`);
|
137 | }
|
138 |
|
139 | if (typeof classConstructor !== 'function') {
|
140 | throw new Error(`ima.ObjectContainer:bind The second ` + `argument has to be a class constructor function, ` + `but ${classConstructor} was provided. Fix alias ` + `${name} for your bind.js file.`);
|
141 | }
|
142 | }
|
143 |
|
144 | let classConstructorEntry = this._entries.get(classConstructor);
|
145 | let nameEntry = this._entries.get(name);
|
146 | let entry = classConstructorEntry || nameEntry;
|
147 |
|
148 | if (classConstructorEntry && !nameEntry && dependencies) {
|
149 | let entry = this._createEntry(classConstructor, dependencies);
|
150 | this._entries.set(name, entry);
|
151 |
|
152 | return this;
|
153 | }
|
154 |
|
155 | if (entry) {
|
156 | this._entries.set(name, entry);
|
157 |
|
158 | if (dependencies) {
|
159 | this._updateEntryValues(entry, classConstructor, dependencies);
|
160 | }
|
161 | } else {
|
162 | let entry = this._createEntry(classConstructor, dependencies);
|
163 | this._entries.set(classConstructor, entry);
|
164 | this._entries.set(name, entry);
|
165 | }
|
166 |
|
167 | return this;
|
168 | }
|
169 |
|
170 | /**
|
171 | * Defines a new constant registered with this object container. Note that
|
172 | * this is the only way of passing {@code string} values to constructors
|
173 | * because the object container treats strings as class, interface, alias
|
174 | * or constant names.
|
175 | *
|
176 | * @param {string} name The constant name.
|
177 | * @param {*} value The constant value.
|
178 | * @return {ObjectContainer} This object container.
|
179 | */
|
180 | constant(name, value) {
|
181 | if ($Debug) {
|
182 | if (this._entries.has(name) || !!this._getEntryFromConstant(name)) {
|
183 | throw new Error(`ima.ObjectContainer:constant The ${name} ` + `constant has already been declared and cannot be ` + `redefined.`);
|
184 | }
|
185 |
|
186 | if (this._bindingState === ObjectContainer.PLUGIN_BINDING_STATE) {
|
187 | throw new Error(`ima.ObjectContainer:constant The ${name} ` + `constant can't be declared in plugin. ` + `The constant must be define in app/config/bind.js file.`);
|
188 | }
|
189 | }
|
190 |
|
191 | let constantEntry = this._createEntry(() => value, [], {
|
192 | writeable: false
|
193 | });
|
194 | constantEntry.sharedInstance = value;
|
195 | this._entries.set(name, constantEntry);
|
196 |
|
197 | return this;
|
198 | }
|
199 |
|
200 | /**
|
201 | * Configures the object loader with the specified default dependencies for
|
202 | * the specified class.
|
203 | *
|
204 | * New instances of the class created by this object container will receive
|
205 | * the provided dependencies into constructor unless custom dependencies
|
206 | * are provided.
|
207 | *
|
208 | * @template T
|
209 | * @param {function(new: T, ...*)} classConstructor The class constructor.
|
210 | * @param {?*[]} dependencies The dependencies to pass into the
|
211 | * constructor function.
|
212 | * @return {ObjectContainer} This object container.
|
213 | */
|
214 | inject(classConstructor, dependencies) {
|
215 | if ($Debug) {
|
216 | if (typeof classConstructor !== 'function') {
|
217 | throw new Error(`ima.ObjectContainer:inject The first ` + `argument has to be a class constructor function, ` + `but ${classConstructor} was provided. Fix your ` + `bind.js file.`);
|
218 | }
|
219 |
|
220 | if (this._entries.has(classConstructor) && this._bindingState === ObjectContainer.PLUGIN_BINDING_STATE) {
|
221 | throw new Error(`ima.ObjectContainer:inject The ` + `${classConstructor.name} has already had its ` + `default dependencies configured, and the object ` + `container is currently locked, therefore the ` + `dependency configuration cannot be override. The ` + `dependencies of the provided class must be ` + `overridden from the application's bind.js ` + `configuration file.`);
|
222 | }
|
223 | }
|
224 |
|
225 | let classConstructorEntry = this._entries.get(classConstructor);
|
226 | if (classConstructorEntry) {
|
227 | if (dependencies) {
|
228 | this._updateEntryValues(classConstructorEntry, classConstructor, dependencies);
|
229 | }
|
230 | } else {
|
231 | classConstructorEntry = this._createEntry(classConstructor, dependencies);
|
232 | this._entries.set(classConstructor, classConstructorEntry);
|
233 | }
|
234 |
|
235 | return this;
|
236 | }
|
237 |
|
238 | /**
|
239 | * Configures the default implementation of the specified interface to use
|
240 | * when an implementation provider of the specified interface is requested
|
241 | * from this object container.
|
242 | *
|
243 | * The implementation constructor will obtain the provided default
|
244 | * dependencies or the dependencies provided to the {@codelink create()}
|
245 | * method.
|
246 | *
|
247 | * @template {Interface}
|
248 | * @template {Implementation} extends Interface
|
249 | * @param {function(new: Interface)} interfaceConstructor The constructor
|
250 | * of the interface representing the service.
|
251 | * @param {function(new: Implementation, ...*)} implementationConstructor
|
252 | * The constructor of the class implementing the service interface.
|
253 | * @param {?*[]} dependencies The dependencies to pass into the
|
254 | * constructor function.
|
255 | * @return {ObjectContainer} This object container.
|
256 | */
|
257 | provide(interfaceConstructor, implementationConstructor, dependencies) {
|
258 | if ($Debug) {
|
259 | if (this._entries.has(interfaceConstructor) && this._bindingState === ObjectContainer.PLUGIN_BINDING_STATE) {
|
260 | throw new Error('ima.ObjectContainer:provide The ' + 'implementation of the provided interface ' + `(${interfaceConstructor.name}) has already been ` + `configured and cannot be overridden.`);
|
261 | }
|
262 |
|
263 | // check that implementation really extends interface
|
264 | let prototype = implementationConstructor.prototype;
|
265 | if (!(prototype instanceof interfaceConstructor)) {
|
266 | throw new Error('ima.ObjectContainer:provide The specified ' + `class (${implementationConstructor.name}) does not ` + `implement the ${interfaceConstructor.name} ` + `interface.`);
|
267 | }
|
268 | }
|
269 |
|
270 | let classConstructorEntry = this._entries.get(implementationConstructor);
|
271 | if (classConstructorEntry) {
|
272 | this._entries.set(interfaceConstructor, classConstructorEntry);
|
273 |
|
274 | if (dependencies) {
|
275 | this._updateEntryValues(classConstructorEntry, implementationConstructor, dependencies);
|
276 | }
|
277 | } else {
|
278 | classConstructorEntry = this._createEntry(implementationConstructor, dependencies);
|
279 | this._entries.set(implementationConstructor, classConstructorEntry);
|
280 | this._entries.set(interfaceConstructor, classConstructorEntry);
|
281 | }
|
282 |
|
283 | return this;
|
284 | }
|
285 |
|
286 | /**
|
287 | * Retrieves the shared instance or value of the specified constant, alias,
|
288 | * class or factory function, interface, or fully qualified namespace path
|
289 | * (the method checks these in this order in case of a name clash).
|
290 | *
|
291 | * The instance or value is created lazily the first time it is requested.
|
292 | *
|
293 | * @template T
|
294 | * @param {(string|function(new: T, ...*)|function(...*): T)} name The name
|
295 | * of the alias, class, interface, or the class, interface or a
|
296 | * factory function.
|
297 | * @return {T} The shared instance or value.
|
298 | */
|
299 | get(name) {
|
300 | let entry = this._getEntry(name);
|
301 |
|
302 | if (entry.sharedInstance === null) {
|
303 | entry.sharedInstance = this._createInstanceFromEntry(entry);
|
304 | }
|
305 |
|
306 | return entry.sharedInstance;
|
307 | }
|
308 |
|
309 | /**
|
310 | * Returns the class constructor function of the specified class.
|
311 | *
|
312 | * @template T
|
313 | * @param {string|function(new: T, ...*)} name The name by which the class
|
314 | * is registered with this object container.
|
315 | * @return {function(new: T, ...*)} The constructor function.
|
316 | */
|
317 | getConstructorOf(name) {
|
318 | let entry = this._getEntry(name);
|
319 |
|
320 | return entry.classConstructor;
|
321 | }
|
322 |
|
323 | /**
|
324 | * Returns {@code true} if the specified object, class or resource is
|
325 | * registered with this object container.
|
326 | *
|
327 | * @template T
|
328 | * @param {string|function(new: T, ...*)} name The resource name.
|
329 | * @return {boolean} {@code true} if the specified object, class or
|
330 | * resource is registered with this object container.
|
331 | */
|
332 | has(name) {
|
333 | return this._entries.has(name) || !!this._getEntryFromConstant(name) || !!this._getEntryFromNamespace(name) || !!this._getEntryFromClassConstructor(name);
|
334 | }
|
335 |
|
336 | /**
|
337 | * Creates a new instance of the class or retrieves the value generated by
|
338 | * the factory function identified by the provided name, class, interface,
|
339 | * or factory function, passing in the provided dependencies.
|
340 | *
|
341 | * The method uses the dependencies specified when the class, interface or
|
342 | * factory function has been registered with the object container if no
|
343 | * custom dependencies are provided.
|
344 | *
|
345 | * @template T
|
346 | * @param {(string|function(new: T, ...*)|function(...*): T)} name The name
|
347 | * of the alias, class, interface, or the class, interface or a
|
348 | * factory function to use.
|
349 | * @param {?*[]} dependencies The dependencies to pass into the
|
350 | * constructor or factory function.
|
351 | * @return {T} Created instance or generated value.
|
352 | */
|
353 | create(name, dependencies) {
|
354 | let entry = this._getEntry(name);
|
355 |
|
356 | return this._createInstanceFromEntry(entry, dependencies);
|
357 | }
|
358 |
|
359 | /**
|
360 | * Clears all entries from this object container and resets the locking
|
361 | * mechanism of this object container.
|
362 | *
|
363 | * @return {ObjectContainer} This object container.
|
364 | */
|
365 | clear() {
|
366 | this._entries.clear();
|
367 | this._bindingState = null;
|
368 |
|
369 | return this;
|
370 | }
|
371 |
|
372 | /**
|
373 | *
|
374 | * @param {?string} bindingState
|
375 | */
|
376 | setBindingState(bindingState) {
|
377 | if (this._bindingState === ObjectContainer.APP_BINDING_STATE) {
|
378 | throw new Error(`ima.ObjectContainer:setBindingState The setBindingState() ` + `method has to be called only by the bootstrap script. Other ` + `calls are not allowed.`);
|
379 | }
|
380 |
|
381 | this._bindingState = bindingState;
|
382 | }
|
383 |
|
384 | /**
|
385 | * Retrieves the entry for the specified constant, alias, class or factory
|
386 | * function, interface, or fully qualified namespace path (the method
|
387 | * checks these in this order in case of a name clash).
|
388 | *
|
389 | * The method retrieves an existing entry even if a qualified namespace
|
390 | * path is provided (if the target class or interface has been configured
|
391 | * in this object container).
|
392 | *
|
393 | * The method throws an {@codelink Error} if no such constant, alias,
|
394 | * registry, interface implementation is known to this object container and
|
395 | * the provided identifier is not a valid namespace path specifying an
|
396 | * existing class, interface or value.
|
397 | *
|
398 | * @template T
|
399 | * @param {string|function(new: T, ...*)} name Name of a constant or alias,
|
400 | * factory function, class or interface constructor, or a fully
|
401 | * qualified namespace path.
|
402 | * @return {?Entry<T>} The retrieved entry.
|
403 | * @throws {Error} If no such constant, alias, registry, interface
|
404 | * implementation is known to this object container.
|
405 | */
|
406 | _getEntry(name) {
|
407 | let entry = this._entries.get(name) || this._getEntryFromConstant(name) || this._getEntryFromNamespace(name) || this._getEntryFromClassConstructor(name);
|
408 |
|
409 | if ($Debug) {
|
410 | if (!entry) {
|
411 | throw new Error(`ima.ObjectContainer:_getEntry There is no constant, ` + `alias, registered class, registered interface with ` + `configured implementation or namespace entry ` + `identified as ${name}. Check your bind.js file for ` + `typos or register ${name} with the object container.`);
|
412 | }
|
413 | }
|
414 |
|
415 | return entry;
|
416 | }
|
417 |
|
418 | /**
|
419 | * The method update classConstructor and dependencies for defined entry.
|
420 | * The entry throw Error for constants and if you try override dependencies
|
421 | * more than once.
|
422 | *
|
423 | * @template T
|
424 | * @param {(function(new: T, ...*)|function(...*): T)} classConstructor The
|
425 | * class constructor or factory function.
|
426 | * @param {Entry} entry The entry representing the class that should
|
427 | * have its instance created or factory faction to use to create a
|
428 | * value.
|
429 | * @param {*[]} dependencies The dependencies to pass into the
|
430 | * constructor or factory function.
|
431 | */
|
432 | _updateEntryValues(entry, classConstructor, dependencies) {
|
433 | entry.classConstructor = classConstructor;
|
434 | entry.dependencies = dependencies;
|
435 | }
|
436 |
|
437 | /**
|
438 | * Creates a new entry for the provided class or factory function, the
|
439 | * provided dependencies and entry options.
|
440 | *
|
441 | * @template T
|
442 | * @param {(function(new: T, ...*)|function(...*): T)} classConstructor The
|
443 | * class constructor or factory function.
|
444 | * @param {?*[]} [dependencies] The dependencies to pass into the
|
445 | * constructor or factory function.
|
446 | * @param {{ writeable: boolean }} options
|
447 | * @return {T} Created instance or generated value.
|
448 | */
|
449 | _createEntry(classConstructor, dependencies, options) {
|
450 | if ((!dependencies || dependencies.length === 0) && Array.isArray(classConstructor.$dependencies)) {
|
451 | dependencies = classConstructor.$dependencies;
|
452 | }
|
453 |
|
454 | return new Entry(classConstructor, dependencies, options);
|
455 | }
|
456 |
|
457 | /**
|
458 | * Creates a new instance of the class or retrieves the value generated by
|
459 | * the factory function represented by the provided entry, passing in the
|
460 | * provided dependencies.
|
461 | *
|
462 | * The method uses the dependencies specified by the entry if no custom
|
463 | * dependencies are provided.
|
464 | *
|
465 | * @template T
|
466 | * @param {Entry<T>} entry The entry representing the class that should
|
467 | * have its instance created or factory faction to use to create a
|
468 | * value.
|
469 | * @param {*[]} [dependencies=[]] The dependencies to pass into the
|
470 | * constructor or factory function.
|
471 | * @return {T} Created instance or generated value.
|
472 | */
|
473 | _createInstanceFromEntry(entry, dependencies = []) {
|
474 | if (dependencies.length === 0) {
|
475 | dependencies = [];
|
476 |
|
477 | for (let dependency of entry.dependencies) {
|
478 | if (['function', 'string'].indexOf(typeof dependency) > -1) {
|
479 | dependencies.push(this.get(dependency));
|
480 | } else {
|
481 | dependencies.push(dependency);
|
482 | }
|
483 | }
|
484 | }
|
485 | let constructor = entry.classConstructor;
|
486 |
|
487 | return new constructor(...dependencies);
|
488 | }
|
489 |
|
490 | /**
|
491 | * Retrieves the constant value denoted by the provided fully qualified
|
492 | * composition name.
|
493 | *
|
494 | * The method returns the entry for the constant if the constant is registered
|
495 | * with this object container, otherwise return {@code null}.
|
496 | *
|
497 | * Finally, if the constant composition name does not resolve to value,
|
498 | * the method return {@code null}.
|
499 | *
|
500 | * @param {string} compositionName
|
501 | * @return {?Entry<*>} An entry representing the value at the specified
|
502 | * composition name in the constants. The method returns {@code null}
|
503 | * if the specified composition name does not exist in the constants.
|
504 | */
|
505 | _getEntryFromConstant(compositionName) {
|
506 | //TODO entries must be
|
507 | if (typeof compositionName !== 'string') {
|
508 | return null;
|
509 | }
|
510 |
|
511 | let objectProperties = compositionName.split('.');
|
512 | let constantValue = this._entries.has(objectProperties[0]) ? this._entries.get(objectProperties[0]).sharedInstance : null;
|
513 |
|
514 | let pathLength = objectProperties.length;
|
515 | for (let i = 1; i < pathLength && constantValue; i++) {
|
516 | constantValue = constantValue[objectProperties[i]];
|
517 | }
|
518 |
|
519 | if (constantValue !== undefined && constantValue !== null) {
|
520 | let entry = this._createEntry(() => constantValue, [], {
|
521 | writeable: false
|
522 | });
|
523 | entry.sharedInstance = constantValue;
|
524 |
|
525 | return entry;
|
526 | }
|
527 |
|
528 | return null;
|
529 | }
|
530 |
|
531 | /**
|
532 | * Retrieves the class denoted by the provided fully qualified name within
|
533 | * the application namespace.
|
534 | *
|
535 | * The method then checks whether there are dependecies configured for the
|
536 | * class, no matter whether the class is an implementation class or an
|
537 | * "interface" class.
|
538 | *
|
539 | * The method returns the entry for the class if the class is registered
|
540 | * with this object container, otherwise an unregistered entry is created
|
541 | * and returned.
|
542 | *
|
543 | * Finally, if the namespace path does not resolve to a class, the method
|
544 | * return an unregistered entry resolved to the value denoted by the
|
545 | * namespace path.
|
546 | *
|
547 | * Alternatively, if a constructor function is passed in instead of a
|
548 | * namespace path, the method returns {@code null}.
|
549 | *
|
550 | * @template T
|
551 | * @param {(string|function(new: T, ...*))} path Namespace path pointing to
|
552 | * a class or a value in the application namespace, or a constructor
|
553 | * function.
|
554 | * @return {?Entry<T>} An entry representing the value or class at the
|
555 | * specified path in the namespace. The method returns {@code null}
|
556 | * if the specified path does not exist in the namespace.
|
557 | */
|
558 | _getEntryFromNamespace(path) {
|
559 | if (typeof path !== 'string' || !this._namespace.has(path)) {
|
560 | return null;
|
561 | }
|
562 |
|
563 | let namespaceValue = this._namespace.get(path);
|
564 |
|
565 | if (typeof namespaceValue === 'function') {
|
566 | if (this._entries.has(namespaceValue)) {
|
567 | return this._entries.get(namespaceValue);
|
568 | }
|
569 |
|
570 | return this._createEntry(namespaceValue);
|
571 | }
|
572 |
|
573 | let entry = this._createEntry(() => namespaceValue);
|
574 | entry.sharedInstance = namespaceValue;
|
575 | return entry;
|
576 | }
|
577 |
|
578 | /**
|
579 | * Retrieves the class denoted by the provided class constructor.
|
580 | *
|
581 | * The method then checks whether there are defined {@code $dependecies}
|
582 | * property for class. Then the class is registered to this object
|
583 | * container.
|
584 | *
|
585 | * The method returns the entry for the class if the specified class
|
586 | * does not have defined {@code $dependencies} property return
|
587 | * {@code null}.
|
588 | *
|
589 | * @template T
|
590 | * @param {function(new: T, ...*)} classConstructor
|
591 | * @return {?Entry<T>} An entry representing the value at the specified
|
592 | * classConstructor. The method returns {@code null}
|
593 | * if the specified classConstructor does not have defined
|
594 | * {@code $dependencies}.
|
595 | */
|
596 | _getEntryFromClassConstructor(classConstructor) {
|
597 | if (typeof classConstructor === 'function' && Array.isArray(classConstructor.$dependencies)) {
|
598 | let entry = this._createEntry(classConstructor, classConstructor.$dependencies);
|
599 | this._entries.set(classConstructor, entry);
|
600 |
|
601 | return entry;
|
602 | }
|
603 |
|
604 | return null;
|
605 | }
|
606 | }
|
607 |
|
608 | exports.default = ObjectContainer;
|
609 | _namespace2.default.ima.ObjectContainer = ObjectContainer;
|
610 |
|
611 | /**
|
612 | * Object container entry, representing either a class, interface, constant or
|
613 | * an alias.
|
614 | *
|
615 | * @template T
|
616 | */
|
617 | class Entry {
|
618 | /**
|
619 | * Initializes the entry.
|
620 | *
|
621 | * @param {(function(new: T, ...*)|function(...*): T)} classConstructor The
|
622 | * class constructor or constant value getter.
|
623 | * @param {*[]} [dependencies=[]] The dependencies to pass into the
|
624 | * constructor function.
|
625 | * @param {?{ writeable: boolean }} [options] The Entry options.
|
626 | */
|
627 | constructor(classConstructor, dependencies, options) {
|
628 | /**
|
629 | * The constructor of the class represented by this entry, or the
|
630 | * getter of the value of the constant represented by this entry.
|
631 | *
|
632 | * @type {(function(new: T, ...*)|function(...*): T)}
|
633 | */
|
634 | this.classConstructor = classConstructor;
|
635 |
|
636 | /**
|
637 | * The shared instance of the class represented by this entry.
|
638 | *
|
639 | * @type {T}
|
640 | */
|
641 | this.sharedInstance = null;
|
642 |
|
643 | /**
|
644 | * The Entry options.
|
645 | *
|
646 | * @type {{ writeable: boolean }}
|
647 | */
|
648 | this._options = options || {
|
649 | writeable: true
|
650 | };
|
651 |
|
652 | /**
|
653 | * Dependencies of the class constructor of the class represented by
|
654 | * this entry.
|
655 | *
|
656 | * @type {*[]}
|
657 | */
|
658 | this._dependencies = dependencies || [];
|
659 |
|
660 | /**
|
661 | * The override counter
|
662 | *
|
663 | * @type {number}
|
664 | */
|
665 | this._overrideCounter = 0;
|
666 | }
|
667 |
|
668 | set dependencies(dependencies) {
|
669 | if ($Debug) {
|
670 | if (!this.writeable) {
|
671 | throw new Error(`The entry is constant and you ` + `can't redefined their dependencies ${dependencies}.`);
|
672 | }
|
673 |
|
674 | if (this._overrideCounter >= 1) {
|
675 | throw new Error(`The dependencies entry can't be overrided more than once.` + `Fix your bind.js file for classConstructor ${this.classConstructor.name}.`);
|
676 | }
|
677 | }
|
678 |
|
679 | this._dependencies = dependencies;
|
680 | this._overrideCounter++;
|
681 | }
|
682 |
|
683 | get dependencies() {
|
684 | return this._dependencies;
|
685 | }
|
686 |
|
687 | get writeable() {
|
688 | return this._options.writeable;
|
689 | }
|
690 | }
|
691 |
|
692 | typeof $IMA !== 'undefined' && $IMA !== null && $IMA.Loader && $IMA.Loader.register('ima/ObjectContainer', [], function (_export, _context) {
|
693 | ;
|
694 | return {
|
695 | setters: [],
|
696 | execute: function () {
|
697 | _export('default', exports.default);
|
698 | }
|
699 | };
|
700 | });
|