@teqfw/di 2.0.2 → 2.0.4
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.
- package/CHANGELOG.md +11 -0
- package/README.md +220 -149
- package/ai/AGENTS.md +75 -0
- package/ai/concepts.md +66 -0
- package/ai/container.md +72 -0
- package/ai/dependency-id.md +116 -0
- package/ai/extensions.md +71 -0
- package/ai/package-api.ts +440 -0
- package/ai/usage.md +244 -0
- package/jsconfig.json +4 -4
- package/package.json +2 -1
package/ai/container.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# container.md
|
|
2
|
+
|
|
3
|
+
Version: 20260307
|
|
4
|
+
|
|
5
|
+
## Role of the Container
|
|
6
|
+
|
|
7
|
+
The container provides the operational mechanism that links ES modules at runtime. It resolves dependency identifiers, loads modules, instantiates exported factories, and returns fully linked objects. The container serves as the composition root of the system and centralizes all dependency resolution.
|
|
8
|
+
|
|
9
|
+
Application modules do not resolve dependencies themselves and do not construct collaborators directly. Instead, they request dependencies from the container using dependency identifiers.
|
|
10
|
+
|
|
11
|
+
## Container Responsibilities
|
|
12
|
+
|
|
13
|
+
The container performs the following responsibilities:
|
|
14
|
+
|
|
15
|
+
- interpret dependency identifiers
|
|
16
|
+
- resolve identifiers into module locations
|
|
17
|
+
- load ES modules dynamically
|
|
18
|
+
- instantiate exported factories
|
|
19
|
+
- apply preprocess and postprocess handlers
|
|
20
|
+
- manage object lifecycle semantics
|
|
21
|
+
- freeze linked objects before returning them
|
|
22
|
+
|
|
23
|
+
These responsibilities ensure deterministic runtime linking between modules.
|
|
24
|
+
|
|
25
|
+
## Dependency Resolution Pipeline
|
|
26
|
+
|
|
27
|
+
When a dependency is requested, the container processes the request through a deterministic pipeline consisting of the following stages:
|
|
28
|
+
|
|
29
|
+
1. **Parse** — interpret the dependency identifier.
|
|
30
|
+
2. **Preprocess** — allow registered preprocess handlers to transform the identifier.
|
|
31
|
+
3. **Resolve** — translate the identifier into a module reference.
|
|
32
|
+
4. **Instantiate** — load the module and create the object using the selected export.
|
|
33
|
+
5. **Postprocess** — apply wrapper handlers to the created object.
|
|
34
|
+
6. **Lifecycle** — apply lifecycle semantics such as singleton caching or instance creation.
|
|
35
|
+
7. **Freeze** — freeze the resulting object before returning it.
|
|
36
|
+
|
|
37
|
+
This pipeline ensures that all dependencies are created and linked through a consistent process.
|
|
38
|
+
|
|
39
|
+
## Container API
|
|
40
|
+
|
|
41
|
+
The container exposes a minimal public interface used by application code and configuration code.
|
|
42
|
+
|
|
43
|
+
The core operations are:
|
|
44
|
+
|
|
45
|
+
- **register(identifier, value)** — register a predefined dependency or instance in the container.
|
|
46
|
+
- **get(identifier)** — resolve a dependency identifier and return the linked object.
|
|
47
|
+
- **addPreprocess(handler)** — register a handler that can transform dependency identifiers before resolution.
|
|
48
|
+
- **addPostprocess(handler)** — register a handler that can modify created objects after instantiation.
|
|
49
|
+
|
|
50
|
+
The exact semantics of dependency identifiers are defined in **dependency-id.md**.
|
|
51
|
+
|
|
52
|
+
## Container State Model
|
|
53
|
+
|
|
54
|
+
The container operates in three states:
|
|
55
|
+
|
|
56
|
+
- **initial** — the container is being configured and dependencies may be registered.
|
|
57
|
+
- **active** — the container resolves dependencies and produces linked objects.
|
|
58
|
+
- **failed** — the container has encountered an unrecoverable error.
|
|
59
|
+
|
|
60
|
+
If an error occurs during dependency resolution or any pipeline stage, the container transitions to the **failed** state. Once the container enters this state, all subsequent dependency requests are rejected.
|
|
61
|
+
|
|
62
|
+
This fail-fast behavior prevents partially linked systems from continuing execution.
|
|
63
|
+
|
|
64
|
+
## Object Linking and Freezing
|
|
65
|
+
|
|
66
|
+
Objects returned by the container represent linked components of the application. After an object is created and all pipeline stages are completed, the container freezes the object before returning it.
|
|
67
|
+
|
|
68
|
+
Freezing ensures that:
|
|
69
|
+
|
|
70
|
+
- linked objects cannot be modified by consumers
|
|
71
|
+
- shared instances remain stable
|
|
72
|
+
- the container remains the only authority responsible for object construction and linking
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# dependency-id.md
|
|
2
|
+
|
|
3
|
+
Version: 20260307
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
Dependencies in the container are addressed using **Canonical Dependency Codes (CDC)**. A CDC is a structured identifier interpreted by the container to determine which module must be loaded, which export must be used, and how the resulting object must be instantiated.
|
|
8
|
+
|
|
9
|
+
CDC provides a stable logical addressing mechanism that is independent of file paths and runtime environments.
|
|
10
|
+
|
|
11
|
+
## Canonical Form
|
|
12
|
+
|
|
13
|
+
A CDC follows the canonical structure:
|
|
14
|
+
|
|
15
|
+
```txt
|
|
16
|
+
[PlatformPrefix]ModuleName[__ExportName][Lifecycle][WrapperSuffixes]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The components have the following roles:
|
|
20
|
+
|
|
21
|
+
- **PlatformPrefix** — optional prefix identifying a platform module source.
|
|
22
|
+
- **ModuleName** — logical module identifier within a namespace.
|
|
23
|
+
- **ExportName** — optional named export selector.
|
|
24
|
+
- **Lifecycle** — marker defining instantiation semantics.
|
|
25
|
+
- **WrapperSuffixes** — optional sequence of wrapper identifiers.
|
|
26
|
+
|
|
27
|
+
Each CDC is interpreted deterministically by the container.
|
|
28
|
+
|
|
29
|
+
## Platform Prefix
|
|
30
|
+
|
|
31
|
+
A CDC may reference modules provided by the runtime platform or external packages.
|
|
32
|
+
|
|
33
|
+
The following prefixes are supported:
|
|
34
|
+
|
|
35
|
+
- **`node_`** — reference a built-in Node.js module.
|
|
36
|
+
- **`npm_`** — reference a module from the npm ecosystem.
|
|
37
|
+
|
|
38
|
+
Examples:
|
|
39
|
+
|
|
40
|
+
```txt
|
|
41
|
+
node_fs$
|
|
42
|
+
npm_lodash$
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
If no platform prefix is present, the identifier refers to an application module resolved through namespace mapping.
|
|
46
|
+
|
|
47
|
+
## Module Identification
|
|
48
|
+
|
|
49
|
+
The **ModuleName** identifies the module that provides the dependency. Module identifiers use namespace-based naming and are translated into filesystem paths according to namespace resolution rules described in **container.md**.
|
|
50
|
+
|
|
51
|
+
Identifier segments separated by underscores correspond to directory boundaries in the module path.
|
|
52
|
+
|
|
53
|
+
Example:
|
|
54
|
+
|
|
55
|
+
```txt
|
|
56
|
+
App_Service_User
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
maps to a module located at:
|
|
60
|
+
|
|
61
|
+
```txt
|
|
62
|
+
AppRoot/Service/User.js
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Export Selection
|
|
66
|
+
|
|
67
|
+
A CDC may reference either the default export of a module or a named export.
|
|
68
|
+
|
|
69
|
+
Named exports are selected using a double underscore separator.
|
|
70
|
+
|
|
71
|
+
Examples:
|
|
72
|
+
|
|
73
|
+
```txt
|
|
74
|
+
App_Service_User$
|
|
75
|
+
App_Service_User__Factory$
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The first identifier resolves the module default export. The second resolves the named export `Factory`.
|
|
79
|
+
|
|
80
|
+
## Lifecycle Markers
|
|
81
|
+
|
|
82
|
+
Lifecycle markers define how the container instantiates and returns objects.
|
|
83
|
+
|
|
84
|
+
The following markers are supported:
|
|
85
|
+
|
|
86
|
+
- **`$`** — singleton lifecycle; the container creates the object once and returns the same instance for subsequent requests.
|
|
87
|
+
- **`$$`** — factory lifecycle; a new instance is created for each request.
|
|
88
|
+
- **`$$$`** — transient lifecycle; the container delegates lifecycle management entirely to the caller.
|
|
89
|
+
|
|
90
|
+
Lifecycle markers are appended at the end of the identifier.
|
|
91
|
+
|
|
92
|
+
## Wrapper Suffixes
|
|
93
|
+
|
|
94
|
+
Wrappers allow postprocessing of created objects. Wrapper identifiers are appended after the lifecycle marker and separated by underscores.
|
|
95
|
+
|
|
96
|
+
Example:
|
|
97
|
+
|
|
98
|
+
```txt
|
|
99
|
+
App_Service_User$$_wrapLog_wrapTrace
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
In this example the container creates a new instance and applies the wrappers `wrapLog` and `wrapTrace` during the postprocess stage.
|
|
103
|
+
|
|
104
|
+
Wrapper behavior is described in **extensions.md**.
|
|
105
|
+
|
|
106
|
+
## Resolution Semantics
|
|
107
|
+
|
|
108
|
+
When the container receives a CDC it performs the following interpretation steps:
|
|
109
|
+
|
|
110
|
+
1. determine the platform prefix and module namespace
|
|
111
|
+
2. resolve the module identifier into a module location
|
|
112
|
+
3. select the requested export
|
|
113
|
+
4. apply lifecycle semantics
|
|
114
|
+
5. apply wrapper suffixes if present
|
|
115
|
+
|
|
116
|
+
These interpretation steps integrate with the dependency resolution pipeline described in **container.md**.
|
package/ai/extensions.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# extensions.md
|
|
2
|
+
|
|
3
|
+
Version: 20260307
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
The container supports controlled extension of the dependency resolution process through **preprocess handlers** and **postprocess wrappers**. These mechanisms allow the behavior of dependency resolution and object creation to be adjusted without modifying container internals.
|
|
8
|
+
|
|
9
|
+
Extensions are registered during container configuration and become part of the deterministic resolution pipeline.
|
|
10
|
+
|
|
11
|
+
## Extension Points
|
|
12
|
+
|
|
13
|
+
Two extension points are available:
|
|
14
|
+
|
|
15
|
+
- **Preprocess handlers** — transform dependency identifiers before resolution.
|
|
16
|
+
- **Postprocess wrappers** — modify or decorate created objects after instantiation.
|
|
17
|
+
|
|
18
|
+
These extension points correspond to the preprocess and postprocess stages of the container pipeline described in **container.md**.
|
|
19
|
+
|
|
20
|
+
## Preprocess Handlers
|
|
21
|
+
|
|
22
|
+
Preprocess handlers receive a dependency identifier before it is interpreted by the container. A handler may transform the identifier and return a modified value that continues through the resolution pipeline.
|
|
23
|
+
|
|
24
|
+
Typical uses of preprocess handlers include:
|
|
25
|
+
|
|
26
|
+
- rewriting dependency identifiers
|
|
27
|
+
- applying identifier aliases
|
|
28
|
+
- enforcing project-specific identifier conventions
|
|
29
|
+
|
|
30
|
+
Preprocess handlers operate only on identifiers and do not interact with instantiated objects.
|
|
31
|
+
|
|
32
|
+
## Postprocess Wrappers
|
|
33
|
+
|
|
34
|
+
Postprocess wrappers operate on objects created by the container. A wrapper receives the instantiated object and may return a modified or decorated version.
|
|
35
|
+
|
|
36
|
+
Wrappers are typically used for:
|
|
37
|
+
|
|
38
|
+
- logging or tracing
|
|
39
|
+
- instrumentation
|
|
40
|
+
- capability injection
|
|
41
|
+
- runtime adaptation of object behavior
|
|
42
|
+
|
|
43
|
+
Wrappers do not modify the dependency resolution logic itself and operate only after object instantiation.
|
|
44
|
+
|
|
45
|
+
## Wrapper Selection
|
|
46
|
+
|
|
47
|
+
Wrappers are applied when their identifiers appear in a CDC. Wrapper identifiers are appended after the lifecycle marker and separated by underscores.
|
|
48
|
+
|
|
49
|
+
Example:
|
|
50
|
+
|
|
51
|
+
```txt
|
|
52
|
+
App_Service_User$$_wrapLog_wrapTrace
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
In this example the container creates a new instance of the dependency and applies the wrappers `wrapLog` and `wrapTrace` during the postprocess stage.
|
|
56
|
+
|
|
57
|
+
## Execution Order
|
|
58
|
+
|
|
59
|
+
Multiple wrappers may be applied to a single dependency. Wrappers are executed in the order in which they appear in the CDC.
|
|
60
|
+
|
|
61
|
+
Each wrapper receives the object returned by the previous wrapper and may return a new object that becomes the input to the next wrapper.
|
|
62
|
+
|
|
63
|
+
## Extension Constraints
|
|
64
|
+
|
|
65
|
+
Extensions must satisfy the following constraints:
|
|
66
|
+
|
|
67
|
+
- they must be registered before the container becomes active
|
|
68
|
+
- they must be deterministic and free of side effects that alter container state
|
|
69
|
+
- they must not bypass lifecycle semantics enforced by the container
|
|
70
|
+
|
|
71
|
+
These constraints ensure that extensions do not compromise deterministic dependency resolution.
|