1 | declare module '@ember/-internals/owner' {
|
2 | /**
|
3 | @module @ember/owner
|
4 | */
|
5 | /**
|
6 | The name for a factory consists of a namespace and the name of a specific type
|
7 | within that namespace, like `'service:session'`.
|
8 |
|
9 | **Note:** `FullName` is *not* a class, just a contract for strings used in the
|
10 | DI system. It is currently documented as a class only due to limits in our
|
11 | documentation infrastructure.
|
12 |
|
13 | @for @ember/owner
|
14 | @class FullName
|
15 | @public
|
16 | */
|
17 | export type FullName<
|
18 | Type extends string = string,
|
19 | Name extends string = string
|
20 | > = `${Type}:${Name}`;
|
21 | /**
|
22 | A type registry for the DI system, which other participants in the DI system
|
23 | can register themselves into with declaration merging. The contract for this
|
24 | type is that its keys are the `Type` from a `FullName`, and each value for a
|
25 | `Type` is another registry whose keys are the `Name` from a `FullName`. The
|
26 | mechanic for providing a registry is [declaration merging][handbook].
|
27 |
|
28 | [handbook]: https://www.typescriptlang.org/docs/handbook/declaration-merging.html
|
29 |
|
30 | For example, Ember's `@ember/service` module includes this set of definitions:
|
31 |
|
32 | ```ts
|
33 | export default class Service extends EmberObject {}
|
34 |
|
35 | // For concrete singleton classes to be merged into.
|
36 | interface Registry extends Record<string, Service> {}
|
37 |
|
38 | declare module '@ember/owner' {
|
39 | service: Registry;
|
40 | }
|
41 | ```
|
42 |
|
43 | Declarations of services can then include the registry:
|
44 |
|
45 | ```ts
|
46 | import Service from '@ember/service';
|
47 |
|
48 | export default class Session extends Service {
|
49 | login(username: string, password: string) {
|
50 | // ...
|
51 | }
|
52 | }
|
53 |
|
54 | declare module '@ember/service' {
|
55 | interface Registry {
|
56 | session: Session;
|
57 | }
|
58 | }
|
59 | ```
|
60 |
|
61 | Then users of the `Owner` API will be able to do things like this with strong
|
62 | type safety guarantees:
|
63 |
|
64 | ```ts
|
65 | getOwner(this)?.lookup('service:session').login("hello", "1234abcd");
|
66 | ```
|
67 |
|
68 | @for @ember/owner
|
69 | @private
|
70 | */
|
71 | export interface DIRegistry {}
|
72 | /**
|
73 | @private
|
74 | */
|
75 | type ResolveFactoryManager<Type extends string, Name extends string> = Type extends ValidType
|
76 | ? Name extends ValidName<Type>
|
77 | ? DIRegistry[Type][Name] extends infer RegistryEntry extends object
|
78 | ? FactoryManager<RegistryEntry>
|
79 | : FactoryManagerDefault
|
80 | : FactoryManagerDefault
|
81 | : FactoryManagerDefault;
|
82 | type FactoryManagerDefault = FactoryManager<object> | undefined;
|
83 | type Lookup<Type extends string, Name extends string> = Type extends ValidType
|
84 | ? Name extends ValidName<Type>
|
85 | ? DIRegistry[Type][Name]
|
86 | : unknown
|
87 | : unknown;
|
88 | /**
|
89 | The common interface for the ability to `register()` an item, shared by the
|
90 | `Owner` and `RegistryProxy` interfaces.
|
91 |
|
92 | @for @ember/owner
|
93 | @class BasicRegistry
|
94 | @private
|
95 | */
|
96 | interface BasicRegistry {
|
97 | /**
|
98 | Registers a factory that can be used for dependency injection (with
|
99 | `inject`) or for service lookup. Each factory is registered with
|
100 | a full name including two parts: `type:name`.
|
101 |
|
102 | A simple example:
|
103 |
|
104 | ```javascript
|
105 | import Application from '@ember/application';
|
106 | import EmberObject from '@ember/object';
|
107 |
|
108 | let App = Application.create();
|
109 |
|
110 | App.Orange = EmberObject.extend();
|
111 | App.register('fruit:favorite', App.Orange);
|
112 | ```
|
113 |
|
114 | Ember will resolve factories from the `App` namespace automatically.
|
115 | For example `App.CarsController` will be discovered and returned if
|
116 | an application requests `controller:cars`.
|
117 |
|
118 | An example of registering a controller with a non-standard name:
|
119 |
|
120 | ```javascript
|
121 | import Application from '@ember/application';
|
122 | import Controller from '@ember/controller';
|
123 |
|
124 | let App = Application.create();
|
125 | let Session = Controller.extend();
|
126 |
|
127 | App.register('controller:session', Session);
|
128 |
|
129 | // The Session controller can now be treated like a normal controller,
|
130 | // despite its non-standard name.
|
131 | App.ApplicationController = Controller.extend({
|
132 | needs: ['session']
|
133 | });
|
134 | ```
|
135 |
|
136 | Registered factories are **instantiated** by having `create`
|
137 | called on them. Additionally they are **singletons**, each time
|
138 | they are looked up they return the same instance.
|
139 |
|
140 | Some examples modifying that default behavior:
|
141 |
|
142 | ```javascript
|
143 | import Application from '@ember/application';
|
144 | import EmberObject from '@ember/object';
|
145 |
|
146 | let App = Application.create();
|
147 |
|
148 | App.Person = EmberObject.extend();
|
149 | App.Orange = EmberObject.extend();
|
150 | App.Email = EmberObject.extend();
|
151 | App.session = EmberObject.create();
|
152 |
|
153 | App.register('model:user', App.Person, { singleton: false });
|
154 | App.register('fruit:favorite', App.Orange);
|
155 | App.register('communication:main', App.Email, { singleton: false });
|
156 | App.register('session', App.session, { instantiate: false });
|
157 | ```
|
158 |
|
159 | @method register
|
160 | @param fullName {String} type:name (e.g., 'model:user')
|
161 | @param factory {Factory|object} (e.g., App.Person)
|
162 | @param options {Object} (optional) disable instantiation or singleton usage
|
163 | @public
|
164 | */
|
165 | register(
|
166 | fullName: FullName,
|
167 | factory: Factory<object> | object,
|
168 | options?: RegisterOptions
|
169 | ): void;
|
170 | }
|
171 | type ValidType = keyof DIRegistry & string;
|
172 | type ValidName<Type extends ValidType> = keyof DIRegistry[Type] & string;
|
173 | /**
|
174 | The common interface for the ability to `lookup()` or get the `factoryFor` an
|
175 | item, shared by the `Owner` and `ContainerProxy` interfaces.
|
176 |
|
177 | @for @ember/owner
|
178 | @class BasicContainer
|
179 | @private
|
180 | */
|
181 | interface BasicContainer {
|
182 | /**
|
183 | Given a fullName return a corresponding instance.
|
184 |
|
185 | The default behavior is for lookup to return a singleton instance.
|
186 | The singleton is scoped to the container, allowing multiple containers
|
187 | to all have their own locally scoped singletons.
|
188 |
|
189 | ```javascript
|
190 | let registry = new Registry();
|
191 | let container = registry.container();
|
192 |
|
193 | registry.register('api:twitter', Twitter);
|
194 |
|
195 | let twitter = container.lookup('api:twitter');
|
196 |
|
197 | twitter instanceof Twitter; // => true
|
198 |
|
199 | // by default the container will return singletons
|
200 | let twitter2 = container.lookup('api:twitter');
|
201 | twitter2 instanceof Twitter; // => true
|
202 |
|
203 | twitter === twitter2; //=> true
|
204 | ```
|
205 |
|
206 | If singletons are not wanted an optional flag can be provided at lookup.
|
207 |
|
208 | ```javascript
|
209 | let registry = new Registry();
|
210 | let container = registry.container();
|
211 |
|
212 | registry.register('api:twitter', Twitter);
|
213 |
|
214 | let twitter = container.lookup('api:twitter', { singleton: false });
|
215 | let twitter2 = container.lookup('api:twitter', { singleton: false });
|
216 |
|
217 | twitter === twitter2; //=> false
|
218 | ```
|
219 |
|
220 | @public
|
221 | @method lookup
|
222 | @param {string} fullName
|
223 | @param {RegisterOptions} options
|
224 | @return {any}
|
225 | */
|
226 | lookup<Type extends string, Name extends string>(
|
227 | fullName: FullName<Type, Name>,
|
228 | options?: RegisterOptions
|
229 | ): Lookup<Type, Name>;
|
230 | /**
|
231 | Given a `FullName`, of the form `"type:name"` return a `FactoryManager`.
|
232 |
|
233 | This method returns a manager which can be used for introspection of the
|
234 | factory's class or for the creation of factory instances with initial
|
235 | properties. The manager is an object with the following properties:
|
236 |
|
237 | * `class` - The registered or resolved class.
|
238 | * `create` - A function that will create an instance of the class with
|
239 | any dependencies injected.
|
240 |
|
241 | For example:
|
242 |
|
243 | ```javascript
|
244 | import { getOwner } from '@ember/application';
|
245 |
|
246 | let owner = getOwner(otherInstance);
|
247 | // the owner is commonly the `applicationInstance`, and can be accessed via
|
248 | // an instance initializer.
|
249 |
|
250 | let factory = owner.factoryFor('service:bespoke');
|
251 |
|
252 | factory.class;
|
253 | // The registered or resolved class. For example when used with an Ember-CLI
|
254 | // app, this would be the default export from `app/services/bespoke.js`.
|
255 |
|
256 | let instance = factory.create({
|
257 | someProperty: 'an initial property value'
|
258 | });
|
259 | // Create an instance with any injections and the passed options as
|
260 | // initial properties.
|
261 | ```
|
262 |
|
263 | Any instances created via the factory's `.create()` method *must* be destroyed
|
264 | manually by the caller of `.create()`. Typically, this is done during the creating
|
265 | objects own `destroy` or `willDestroy` methods.
|
266 |
|
267 | @public
|
268 | @method factoryFor
|
269 | @param {string} fullName
|
270 | @return {FactoryManager}
|
271 | */
|
272 | factoryFor<Type extends string, Name extends string>(
|
273 | fullName: FullName<Type, Name>
|
274 | ): ResolveFactoryManager<Type, Name>;
|
275 | }
|
276 | /**
|
277 | Framework objects in an Ember application (components, services, routes,
|
278 | etc.) are created via a factory and dependency injection system. Each of
|
279 | these objects is the responsibility of an "owner", which handles its
|
280 | instantiation and manages its lifetime.
|
281 |
|
282 | An `Owner` is not a class you construct; it is one the framework constructs
|
283 | for you. The normal way to get access to the relevant `Owner` is using the
|
284 | `getOwner` function.
|
285 |
|
286 | @for @ember/owner
|
287 | @uses BasicRegistry
|
288 | @uses BasicContainer
|
289 | @class Owner
|
290 | @since 4.10.0
|
291 | @public
|
292 | */
|
293 | export default interface Owner extends BasicRegistry, BasicContainer {}
|
294 | /**
|
295 | * Interface representing the options for registering an item as a factory.
|
296 | *
|
297 | * @for @ember/owner
|
298 | * @class RegisterOptions
|
299 | * @public
|
300 | */
|
301 | export interface RegisterOptions {
|
302 | /**
|
303 | Whether to instantiate the item when returning it from a lookup. Defaults
|
304 | to `true`.
|
305 |
|
306 | @property instantiate
|
307 | @type Boolean
|
308 | @optional
|
309 | @default true
|
310 | @public
|
311 | */
|
312 | instantiate?: boolean | undefined;
|
313 | /**
|
314 | Whether the item is a singleton (like a service) and so should return the
|
315 | same instance every time, or should generate a new instance on each call.
|
316 | Defaults to `true`.
|
317 |
|
318 | @property singleton
|
319 | @type Boolean
|
320 | @optional
|
321 | @default true
|
322 | @public
|
323 | */
|
324 | singleton?: boolean | undefined;
|
325 | }
|
326 | /**
|
327 | Registered factories are instantiated by having create called on them.
|
328 | Additionally they are singletons by default, so each time they are looked up
|
329 | they return the same instance.
|
330 |
|
331 | However, that behavior can be modified with the `instantiate` and `singleton`
|
332 | options to the `Owner.register()` method.
|
333 |
|
334 | @for @ember/owner
|
335 | @class Factory
|
336 | @since 4.10.0
|
337 | @public
|
338 | */
|
339 | export interface Factory<T extends object> {
|
340 | /**
|
341 | * A function that will create an instance of the class with any
|
342 | * dependencies injected.
|
343 | *
|
344 | * @method create
|
345 | * @param initialValues {Object} Any values to set on an instance of the class
|
346 | * @return {Object} The item produced by the factory.
|
347 | * @public
|
348 | */
|
349 | create(initialValues?: object): T;
|
350 | }
|
351 | /**
|
352 | The interface representing a manager which can be used for introspection of
|
353 | the factory's class or for the creation of factory instances with initial
|
354 | properties. The manager is an object with the following properties:
|
355 |
|
356 | - `class` - The registered or resolved class.
|
357 | - `create` - A function that will create an instance of the class with any
|
358 | dependencies injected.
|
359 |
|
360 | **Note:** `FactoryManager` is *not* user-constructible; the only legal way
|
361 | to get a `FactoryManager` is via `Owner.factoryFor`.
|
362 |
|
363 | @for @ember/owner
|
364 | @class FactoryManager
|
365 | @extends Factory
|
366 | @public
|
367 | */
|
368 | export interface FactoryManager<T extends object> extends Factory<T> {
|
369 | /**
|
370 | The registered or resolved class.
|
371 |
|
372 | @property class
|
373 | @type Factory
|
374 | @public
|
375 | */
|
376 | readonly class: Factory<T>;
|
377 | }
|
378 | /**
|
379 | * A record mapping all known items of a given type: if the item is known it
|
380 | * will be `true`; otherwise it will be `false` or `undefined`.
|
381 | */
|
382 | export type KnownForTypeResult<Type extends string> = {
|
383 | [Key in FullName<Type, string>]: boolean | undefined;
|
384 | };
|
385 | /**
|
386 | A `Resolver` is the mechanism responsible for looking up code in your
|
387 | application and converting its naming conventions into the actual classes,
|
388 | functions, and templates that Ember needs to resolve its dependencies, for
|
389 | example, what template to render for a given route. It is a system that helps
|
390 | the app resolve the lookup of JavaScript modules agnostic of what kind of
|
391 | module system is used, which can be AMD, CommonJS or just plain globals. It
|
392 | is used to lookup routes, models, components, templates, or anything that is
|
393 | used in your Ember app.
|
394 |
|
395 | This interface is not a concrete class; instead, it represents the contract a
|
396 | custom resolver must implement. Most apps never need to think about this: in
|
397 | the default blueprint, this is supplied by the `ember-resolver` package.
|
398 |
|
399 | @for @ember/owner
|
400 | @class Resolver
|
401 | @since 4.10.0
|
402 | @public
|
403 | */
|
404 | export interface Resolver {
|
405 | /**
|
406 | The one required method for a `Resolver`. Given a string, resolve it to a
|
407 | `Factory`, if one exists.
|
408 |
|
409 | @method resolve
|
410 | @param name {String}
|
411 | @public
|
412 | */
|
413 | resolve: (name: string) => Factory<object> | object | undefined;
|
414 | /**
|
415 | @method knownForType
|
416 | @param type {String}
|
417 | @return {Object}
|
418 | @public
|
419 | */
|
420 | knownForType?: <Type extends string>(type: Type) => KnownForTypeResult<Type>;
|
421 | /**
|
422 | @method lookupDescription
|
423 | @param fullName {String}
|
424 | @return {String}
|
425 | @public
|
426 | */
|
427 | lookupDescription?: (fullName: FullName) => string;
|
428 | /**
|
429 | @method makeToString
|
430 | @param factory {Factory}
|
431 | @param fullName {String}
|
432 | @return {String}
|
433 | @public
|
434 | */
|
435 | makeToString?: (factory: Factory<object>, fullName: FullName) => string;
|
436 | /**
|
437 | @method normalize
|
438 | @param fullName {String}
|
439 | @return {String}
|
440 | @public
|
441 | */
|
442 | normalize?: (fullName: FullName) => FullName;
|
443 | }
|
444 | export interface FactoryClass {
|
445 | positionalParams?: string | string[] | undefined | null;
|
446 | }
|
447 | /**
|
448 | The internal representation of a `Factory`, for the extra detail available for
|
449 | private use internally than we expose to consumers.
|
450 |
|
451 | @for @ember/owner
|
452 | @class InternalFactory
|
453 | @private
|
454 | */
|
455 | export interface InternalFactory<T extends object, C extends FactoryClass | object = FactoryClass>
|
456 | extends Factory<T> {
|
457 | /**
|
458 | @property class
|
459 | @optional
|
460 | @private
|
461 | */
|
462 | class?: C;
|
463 | /**
|
464 | @property name
|
465 | @type String
|
466 | @optional
|
467 | @private
|
468 | */
|
469 | name?: string;
|
470 | /**
|
471 | @property fullName
|
472 | @type String
|
473 | @optional
|
474 | @private
|
475 | */
|
476 | fullName?: FullName;
|
477 | /**
|
478 | @property normalizedName
|
479 | @type String
|
480 | @optional
|
481 | @private
|
482 | */
|
483 | normalizedName?: string;
|
484 | }
|
485 | /**
|
486 | @private
|
487 | @method isFactory
|
488 | @param {Object} obj
|
489 | @return {Boolean}
|
490 | @static
|
491 | */
|
492 | export function isFactory(obj: unknown): obj is InternalFactory<object>;
|
493 | export function getOwner(object: object): InternalOwner | undefined;
|
494 | /**
|
495 | `setOwner` forces a new owner on a given object instance. This is primarily
|
496 | useful in some testing cases.
|
497 |
|
498 | @method setOwner
|
499 | @static
|
500 | @for @ember/owner
|
501 | @param {Object} object An object instance.
|
502 | @param {Owner} object The new owner object of the object instance.
|
503 | @since 2.3.0
|
504 | @public
|
505 | */
|
506 | export function setOwner(object: object, owner: Owner): void;
|
507 | /**
|
508 | * The interface for a container proxy, which is itself a private API used
|
509 | * by the private `ContainerProxyMixin` as part of the base definition of
|
510 | * `EngineInstance`.
|
511 | *
|
512 | * @class ContainerProxy
|
513 | * @for @ember/owner
|
514 | * @private
|
515 | * @extends BasicContainer
|
516 | */
|
517 | export interface ContainerProxy extends BasicContainer {
|
518 | /**
|
519 | Returns an object that can be used to provide an owner to a
|
520 | manually created instance.
|
521 |
|
522 | Example:
|
523 |
|
524 | ```
|
525 | import { getOwner } from '@ember/application';
|
526 |
|
527 | let owner = getOwner(this);
|
528 |
|
529 | User.create(
|
530 | owner.ownerInjection(),
|
531 | { username: 'rwjblue' }
|
532 | )
|
533 | ```
|
534 |
|
535 | @public
|
536 | @method ownerInjection
|
537 | @since 2.3.0
|
538 | @return {Object}
|
539 | */
|
540 | ownerInjection(): object;
|
541 | }
|
542 | /**
|
543 | * @class RegistryProxy
|
544 | * @extends BasicRegistry
|
545 | * @private
|
546 | * @for @ember/owner
|
547 | */
|
548 | export interface RegistryProxy extends BasicRegistry {
|
549 | /**
|
550 | Given a fullName return the corresponding factory.
|
551 |
|
552 | @public
|
553 | @method resolveRegistration
|
554 | @param fullName {String}
|
555 | @return {Function} fullName's factory
|
556 | */
|
557 | resolveRegistration(fullName: FullName): Factory<object> | object | undefined;
|
558 | /**
|
559 | Unregister a factory.
|
560 |
|
561 | ```javascript
|
562 | import Application from '@ember/application';
|
563 | import EmberObject from '@ember/object';
|
564 |
|
565 | let App = Application.create();
|
566 | let User = EmberObject.extend();
|
567 | App.register('model:user', User);
|
568 |
|
569 | App.resolveRegistration('model:user').create() instanceof User //=> true
|
570 |
|
571 | App.unregister('model:user')
|
572 | App.resolveRegistration('model:user') === undefined //=> true
|
573 | ```
|
574 |
|
575 | @public
|
576 | @method unregister
|
577 | @param {String} fullName
|
578 | */
|
579 | unregister(fullName: FullName): void;
|
580 | /**
|
581 | Check if a factory is registered.
|
582 |
|
583 | @public
|
584 | @method hasRegistration
|
585 | @param {String} fullName
|
586 | @return {Boolean}
|
587 | */
|
588 | hasRegistration(fullName: FullName): boolean;
|
589 | /**
|
590 | Return a specific registered option for a particular factory.
|
591 |
|
592 | @public
|
593 | @method registeredOption
|
594 | @param {String} fullName
|
595 | @param {String} optionName
|
596 | @return {Object} options
|
597 | */
|
598 | registeredOption<K extends keyof RegisterOptions>(
|
599 | fullName: FullName,
|
600 | optionName: K
|
601 | ): RegisterOptions[K] | undefined;
|
602 | /**
|
603 | Register options for a particular factory.
|
604 |
|
605 | @public
|
606 | @method registerOptions
|
607 | @param {String} fullName
|
608 | @param {Object} options
|
609 | */
|
610 | registerOptions(fullName: FullName, options: RegisterOptions): void;
|
611 | /**
|
612 | Return registered options for a particular factory.
|
613 |
|
614 | @public
|
615 | @method registeredOptions
|
616 | @param {String} fullName
|
617 | @return {Object} options
|
618 | */
|
619 | registeredOptions(fullName: FullName): RegisterOptions | undefined;
|
620 | /**
|
621 | Allow registering options for all factories of a type.
|
622 |
|
623 | ```javascript
|
624 | import Application from '@ember/application';
|
625 |
|
626 | let App = Application.create();
|
627 | let appInstance = App.buildInstance();
|
628 |
|
629 | // if all of type `connection` must not be singletons
|
630 | appInstance.registerOptionsForType('connection', { singleton: false });
|
631 |
|
632 | appInstance.register('connection:twitter', TwitterConnection);
|
633 | appInstance.register('connection:facebook', FacebookConnection);
|
634 |
|
635 | let twitter = appInstance.lookup('connection:twitter');
|
636 | let twitter2 = appInstance.lookup('connection:twitter');
|
637 |
|
638 | twitter === twitter2; // => false
|
639 |
|
640 | let facebook = appInstance.lookup('connection:facebook');
|
641 | let facebook2 = appInstance.lookup('connection:facebook');
|
642 |
|
643 | facebook === facebook2; // => false
|
644 | ```
|
645 |
|
646 | @public
|
647 | @method registerOptionsForType
|
648 | @param {String} type
|
649 | @param {Object} options
|
650 | */
|
651 | registerOptionsForType(type: string, options: RegisterOptions): void;
|
652 | /**
|
653 | Return the registered options for all factories of a type.
|
654 |
|
655 | @public
|
656 | @method registeredOptionsForType
|
657 | @param {String} type
|
658 | @return {Object} options
|
659 | */
|
660 | registeredOptionsForType(type: string): RegisterOptions | undefined;
|
661 | }
|
662 | /**
|
663 | * @internal This is the same basic interface which is implemented (via the
|
664 | * mixins) by `EngineInstance` and therefore `ApplicationInstance`, which are
|
665 | * the normal interfaces to an `Owner` for end user applications now. However,
|
666 | * going forward, we expect to progressively deprecate and remove the "extra"
|
667 | * APIs which are not exposed on `Owner` itself.
|
668 | */
|
669 | export interface InternalOwner extends RegistryProxy, ContainerProxy {}
|
670 | export {};
|
671 | }
|