@vercube/di 0.0.1-alpha.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,31 @@
1
+ /**
2
+ * This is base class for all property decorators used in application. Decorator class must extend this one.
3
+ * This class instance is created using IOC container so you can @Inject() things here.
4
+ */
5
+ export declare abstract class BaseDecorator<
6
+ T,
7
+ P = any
8
+ > {
9
+ /** Holds options object that is passed as 2nd argument in createDecorator() factory */
10
+ options: T;
11
+ /** Holds class instance that is decorated */
12
+ instance: any;
13
+ /** Holds class prototype that is decorated */
14
+ prototype: P;
15
+ /** Holds property name that was decorated */
16
+ propertyName: string;
17
+ /** Holds property descriptor that was decorated */
18
+ descriptor: PropertyDescriptor;
19
+ /** Holds property index if decorators if for Method Property */
20
+ propertyIndex: number;
21
+ /**
22
+ * This method is called when decorator is created and ready to be used.
23
+ */
24
+ created(): void;
25
+ /**
26
+ * This method is called when decorator is destroyed for cleanup tasks (like unregistering listeners, clearing timers).
27
+ * For standard services it is called at the end of SSR requests and for Vue components it is called when component is
28
+ * destroyed.
29
+ */
30
+ destroyed(): void;
31
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Decorator that automatically executes the decorated method when dependencies are injected.
3
+ * Use this decorator to run initialization logic for runtime-loaded container dependencies.
4
+ * @returns {Function} Decorator function that creates an InitDecorator instance
5
+ */
6
+ export declare function Init(): Function;
@@ -0,0 +1,7 @@
1
+ import { IOC } from "../Types/IOCTypes.js";
2
+ /**
3
+ * Injects a dependency with particular key to service.
4
+ * @param key key to inject
5
+ * @returns decorator
6
+ */
7
+ export declare function Inject(key: IOC.ServiceKey): Function;
@@ -0,0 +1,7 @@
1
+ import { IOC } from "../Types/IOCTypes.js";
2
+ /**
3
+ * Injects a dependency with particular key to service.
4
+ * @param key key to inject
5
+ * @returns decorator
6
+ */
7
+ export declare function InjectOptional(key: IOC.ServiceKey): Function;
@@ -0,0 +1,154 @@
1
+ import { IOC } from "../Types/IOCTypes.js";
2
+ import { ContainerEvents } from "./ContainerEvents.js";
3
+ /**
4
+ * This is new implementation of IOC Container. It mimics Inversify.js container a little bit but its
5
+ * simpler and (probably) more performant on larger scales.
6
+ */
7
+ export declare class Container {
8
+ protected fLocked: boolean;
9
+ protected fDefaultParams: IOC.ContainerParams;
10
+ protected fServices: Map<IOC.ServiceKey, IOC.ServiceDef>;
11
+ protected fNewQueue: Map<IOC.ServiceKey, IOC.ServiceDef>;
12
+ protected fSingletonInstances: Map<IOC.ServiceKey, IOC.Instance>;
13
+ protected fInjectMethod: IOC.InjectMethod;
14
+ protected fContainerEvents: ContainerEvents;
15
+ /**
16
+ * Constructor for container.
17
+ * @param params initial params for container
18
+ */
19
+ constructor(params?: Partial<IOC.ContainerParams>);
20
+ /**
21
+ * Returns array of all service keys. This basically returns keys from all .bindXXX calls.
22
+ * @returns {Array} array of service keys
23
+ */
24
+ get servicesKeys(): IOC.ServiceKey[];
25
+ /**
26
+ * Returns events handler.
27
+ */
28
+ get events(): ContainerEvents;
29
+ /**
30
+ * Binds particular key to container in singleton scope. Multiple queries/injects of this
31
+ * service will always return the same instance.
32
+ *
33
+ * @param key key of service, preferably class or abstract class
34
+ * @param value implementation
35
+ */
36
+ bind<T>(key: IOC.ServiceKey<T>, value?: IOC.ServiceValue<T>): void;
37
+ /**
38
+ * Binds particular key to container in transient scope. Every query/@Inject of this service
39
+ * will have totally brand-new instance of class.
40
+ * @param key key of service, preferably class or abstract class
41
+ * @param value implementation
42
+ */
43
+ bindTransient<T>(key: IOC.ServiceKey<T>, value?: IOC.ServiceValue<T>): void;
44
+ /**
45
+ * Binds particular key class to an existing class instance. If you use this method,
46
+ * class wont be instantiated automatically. The common use case is to
47
+ * share single class instance between two or more containers.
48
+ *
49
+ * @param key key of service, preferably class or abstract class
50
+ * @param value instance of class to be used as resolution
51
+ */
52
+ bindInstance<T>(key: IOC.ServiceKey<T>, value: T): void;
53
+ /**
54
+ * Binds mocked instance to a particular service ID. Its designed to be used in unit tests, where you can quickly
55
+ * replace real IOC implementation with a partial stub. Please note, you are responsible to provide enough data
56
+ * for test to pass, TypeScript wont check it.
57
+ *
58
+ * Example:
59
+ *
60
+ * container.bind(HttpServer, {
61
+ * listen: jest.fn(),
62
+ * });
63
+ *
64
+ * @param key service to be replaced
65
+ * @param mockInstance mock instance
66
+ */
67
+ bindMock<T>(key: IOC.ServiceKey<T>, mockInstance: Partial<T>): void;
68
+ /**
69
+ * Returns implementation for a particular key class. This is the same as @Inject,
70
+ * but triggered programitically.
71
+ * @param key key used in .bind() function to bind key class to implementation class
72
+ * @returns service for identifier
73
+ */
74
+ get<T>(key: IOC.ServiceKey<T>): T;
75
+ /**
76
+ * Returns implementation for a particular key class. This is the same as @Inject,
77
+ * but triggered programitically.
78
+ * @param key key used in .bind() function to bind key class to implementation class
79
+ * @returns service for identifier
80
+ */
81
+ getOptional<T>(key: IOC.ServiceKey<T>): T | null;
82
+ /**
83
+ * Uses the container provider to register multiple things in IOC container at once.
84
+ * @param provider provider that will register new services into IOC container
85
+ */
86
+ use(provider: IOC.ProviderFunc): void;
87
+ /**
88
+ * Expands container during runtime, adding new services to it.
89
+ * @param providers functor that is used to expand the container
90
+ * @param flush whether container should be flushed now or not
91
+ */
92
+ expand(providers: IOC.ProviderFunc | IOC.ProviderFunc[], flush?: boolean): void;
93
+ /**
94
+ * Creates instance of particular class using, respecting all @Injects inside created class.
95
+ * @param classType type of class to instantiate
96
+ * @param method (optional) inject method
97
+ * @returns new class instance with dependencies
98
+ */
99
+ resolve<T>(classType: IOC.Newable<T>, method?: IOC.InjectMethod): T;
100
+ /**
101
+ * Returns all IOC services registered in container.
102
+ * @returns array with all registered services
103
+ */
104
+ getAllServices(): IOC.Instance[];
105
+ /**
106
+ * Unlocks the container, allowing things to be retrieved and used.
107
+ */
108
+ unlock(): void;
109
+ /**
110
+ * Locks the container, disabling to add new services here.
111
+ */
112
+ lock(): void;
113
+ /**
114
+ * Flushes new services queue, registering them into container.
115
+ */
116
+ flushQueue(): void;
117
+ /**
118
+ * Internally retrieve dependency from container.
119
+ * @param key key to get
120
+ * @param parent parent (for debugging purposes)
121
+ * @returns queried instance
122
+ */
123
+ protected internalGet<T>(key: IOC.ServiceKey<T>, parent?: IOC.Instance): T;
124
+ /**
125
+ * Internally retrieve dependency from container.
126
+ * @param key key to get
127
+ * @param parent parent
128
+ * @returns queried instance
129
+ */
130
+ protected internalGetOptional<T>(key: IOC.ServiceKey<T>): T | null;
131
+ /**
132
+ * Internally resolves service def, turning it into class instance with deps injected.
133
+ * @param serviceDef service def to resolve
134
+ * @returns class instance
135
+ */
136
+ protected internalResolve(serviceDef: IOC.ServiceDef): IOC.Instance;
137
+ /**
138
+ * Internally inject deps for particular class..
139
+ * @param instance instance to inject
140
+ * @param method method for injecting dependencies, either lazy or static
141
+ */
142
+ protected internalProcessInjects(instance: IOC.Instance, method: IOC.InjectMethod): void;
143
+ /**
144
+ * Disposes a module, clearing everything allocated to it.
145
+ * @param def def that should be disposed
146
+ */
147
+ protected internalDispose(def: IOC.ServiceDef): void;
148
+ /**
149
+ * Describes particular key for better error messaging.
150
+ * @param key service key
151
+ * @returns string representation of service key
152
+ */
153
+ protected getKeyDescription(key: IOC.ServiceKey): string;
154
+ }
@@ -0,0 +1,18 @@
1
+ import type { IOC } from "../Types/IOCTypes.js";
2
+ export type OnExpandedEvent = (serviceKeys: IOC.ServiceKey[]) => void;
3
+ /**
4
+ * This class allows for container to listen on various IOC events.
5
+ */
6
+ export declare class ContainerEvents {
7
+ private fOnExpanded;
8
+ /**
9
+ * Registers to container "onExpanded" event.
10
+ * @param handler event handler
11
+ */
12
+ onExpanded(handler: OnExpandedEvent): void;
13
+ /**
14
+ * Calls on expanded event.
15
+ * @param serviceKeys key of service we have installed
16
+ */
17
+ callOnExpanded(serviceKeys: IOC.ServiceKey[]): void;
18
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * This module is responsible for internal work of IOC engine inject mechanics. Its written in
3
+ * "raw" (non-OOP) style to maximize simplicity and execution speed.
4
+ */
5
+ import { IOC } from "../Types/IOCTypes.js";
6
+ import { Container } from "./Container.js";
7
+ /**
8
+ * This is a struct that holds information about class dependency - what dependency, which field to inject,etc.
9
+ */
10
+ export interface IClassDep {
11
+ propertyName: string;
12
+ dependency: IOC.ServiceKey;
13
+ type: IOC.DependencyType;
14
+ }
15
+ /**
16
+ * This holds single "metadata" entry for particular class. It holds all @Inject stuff for class.
17
+ */
18
+ export interface IClassMapEntry {
19
+ deps: IClassDep[];
20
+ }
21
+ /**
22
+ * This method registers @Inject() in particular class.
23
+ * @param prototype class prototype for which we register @Inject()
24
+ * @param propertyName name of property that is inejcted
25
+ * @param dependency what we should inject there
26
+ * @param type type of dependency (standard or optional dependency)
27
+ */
28
+ declare function registerInject(prototype: IOC.Prototype, propertyName: string, dependency: IOC.ServiceKey, type: IOC.DependencyType): void;
29
+ /**
30
+ * Returns classmap entry for particular class. It holds information about @Injects for this particular class.
31
+ * @param classType type of class to check
32
+ * @returns class map entry or null if cannot be found
33
+ */
34
+ declare function getEntryForClass(classType: IOC.Newable<unknown>): IClassMapEntry | null;
35
+ /**
36
+ * Returns array of dependencies for particular class instance.
37
+ * @param instance class instance
38
+ * @returns array of @Inject dependencies defined for this class
39
+ */
40
+ declare function getDeps(instance: IOC.Instance): IClassDep[];
41
+ /**
42
+ * This method injects stuff into class, using container passed as first argument. We need container as
43
+ * inject execution is always context based.
44
+ * @param container container instance that is providing dependencies
45
+ * @param instance class instance to inject
46
+ * @param method inject method, "lazy" queries dep during property access while "static" injects during class creation
47
+ */
48
+ declare function injectDeps(container: Container, instance: IOC.Instance, method: IOC.InjectMethod): void;
49
+ export declare const IOCEngine: {
50
+ registerInject: typeof registerInject
51
+ getEntryForClass: typeof getEntryForClass
52
+ injectDeps: typeof injectDeps
53
+ getDeps: typeof getDeps
54
+ };
55
+ export {};
@@ -0,0 +1,48 @@
1
+ import { Container } from "../Domain/Container.js";
2
+ /**
3
+ * This module exports various types used in IOC system.
4
+ */
5
+ export declare namespace IOC {
6
+ type ServiceKey<T = unknown> = symbol | Newable<T> | Abstract<T>;
7
+ type ServiceValue<T = unknown> = Newable<T> | T;
8
+ interface ServiceDef<T = unknown> {
9
+ serviceKey: ServiceKey<T>;
10
+ serviceValue: ServiceValue<T>;
11
+ type: ServiceFactoryType;
12
+ }
13
+ enum ServiceFactoryType {
14
+ CLASS = "CLASS",
15
+ CLASS_SINGLETON = "CLASS_SINGLETON",
16
+ INSTANCE = "INSTANCE",
17
+ }
18
+ interface Newable<T> {
19
+ new (...args: unknown[]): T;
20
+ }
21
+ interface Abstract<T> {
22
+ prototype: T;
23
+ }
24
+ type Instance = any;
25
+ type Prototype = any;
26
+ type ProviderFunc = (container: Container) => void;
27
+ interface ContainerParams {
28
+ createLocked: boolean;
29
+ injectMethod?: IOC.InjectMethod;
30
+ }
31
+ enum InjectMethod {
32
+ LAZY = "LAZY",
33
+ STATIC = "STATIC",
34
+ }
35
+ type Identity = symbol;
36
+ interface ServiceMap {
37
+ [key: string]: ServiceMapEntry;
38
+ }
39
+ type ServiceMapEntry = () => ServiceMapTask | ServiceMapTask[];
40
+ type ServiceMapTask = Promise<{
41
+ default: IOC.ProviderFunc
42
+ }>;
43
+ type Stack = (ServiceKey | Instance)[];
44
+ enum DependencyType {
45
+ STANDARD = 0,
46
+ OPTIONAL = 1,
47
+ }
48
+ }
@@ -0,0 +1,79 @@
1
+ import { type BaseDecorator } from "../Common/BaseDecorators.js";
2
+ import { Container } from "../Domain/Container.js";
3
+ import { IOC } from "../Types/IOCTypes.js";
4
+ /**
5
+ * This function generates new service key for particular service. Providing
6
+ * name is mandatory because, unlike classes, those unique symbols do not infer
7
+ * their names from code.
8
+ *
9
+ * @param name name of the service
10
+ * @returns unique service identity
11
+ */
12
+ export declare function Identity(name: string): IOC.Identity;
13
+ /**
14
+ * A simple type of constructor for class "T"
15
+ */
16
+ export interface IClassType<T> {
17
+ new (): T;
18
+ }
19
+ /**
20
+ * Holds decorator entry struct. It is saved in __decorators array for every class and holds
21
+ * various informations.
22
+ */
23
+ export interface IDecoratorEntry {
24
+ classType: any;
25
+ params: any;
26
+ target: any;
27
+ propertyName: string;
28
+ descriptor: PropertyDescriptor;
29
+ }
30
+ /**
31
+ * This is a type for every class instance that is decorated. It should contain hidden __decorators
32
+ * array that holds information about all decorators used in this class. It will be used later for
33
+ * turning those declarations for real code.
34
+ */
35
+ export interface IDecoratedPrototype {
36
+ __decorators?: IDecoratorEntry[];
37
+ __metadata?: any;
38
+ }
39
+ export interface IDecoratedInstance {
40
+ __decoratorInstances?: BaseDecorator<any>[];
41
+ }
42
+ /**
43
+ * This function creates ES6 decorator based on class that was passed in argument.
44
+ *
45
+ * @param decoratorClass class of decorator that will be used
46
+ * @param params custom options object that will be availalbe in "options" property of decorator class
47
+ * @return ES6 decorator function
48
+ */
49
+ export declare function createDecorator<
50
+ P,
51
+ T extends BaseDecorator<P>
52
+ >(decoratorClass: IClassType<T>, params: P): Function;
53
+ /**
54
+ * This function initializes all registered decorators on particular instance. It must be called in order
55
+ * for decorator code work in particular class.
56
+ * @param target class instance to sue
57
+ * @param container IOC container for context
58
+ */
59
+ export declare function initializeDecorators(target: IDecoratedInstance, container: Container): void;
60
+ /**
61
+ * This function releases all decorators applied to target instance by calling their .destroyed()
62
+ * method. Its used to provide a way for cleanup for decorators. @see BaseDecorator.destroy()
63
+ *
64
+ * @param target instance of class that should have decorators cleaned up
65
+ * @param container ioc container
66
+ */
67
+ export declare function destroyDecorators(target: IDecoratedInstance, container: Container): void;
68
+ /**
69
+ * This function is responsible for preparing IOC container to work with all decorators. It simply
70
+ * initializes all decorators on all services registered.
71
+ * @param container IOC container
72
+ */
73
+ export declare function initializeContainer(container: Container): void;
74
+ /**
75
+ * This function is responsible for preparing IOC container to work with all decorators. It simply
76
+ * initializes all decorators on all services registered.
77
+ * @param container IOC container
78
+ */
79
+ export declare function destroyContainer(container: Container): void;