@nexus-ioc/core 0.6.1 → 0.7.0

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.
Files changed (222) hide show
  1. package/README.md +731 -1
  2. package/dist/cjs/browser.js +2 -2
  3. package/dist/cjs/browser.js.map +1 -1
  4. package/dist/cjs/core/child-module.js +32 -0
  5. package/dist/cjs/core/child-module.js.map +1 -0
  6. package/dist/cjs/core/graph/analyze-lazy-module.js +54 -0
  7. package/dist/cjs/core/graph/analyze-lazy-module.js.map +1 -0
  8. package/dist/cjs/core/graph/analyze-module.js +11 -0
  9. package/dist/cjs/core/graph/analyze-module.js.map +1 -1
  10. package/dist/cjs/core/graph/module-graph.js +685 -70
  11. package/dist/cjs/core/graph/module-graph.js.map +1 -1
  12. package/dist/cjs/core/injection/injection-context.js +29 -0
  13. package/dist/cjs/core/injection/injection-context.js.map +1 -0
  14. package/dist/cjs/core/lazy-module-loader.js +41 -0
  15. package/dist/cjs/core/lazy-module-loader.js.map +1 -0
  16. package/dist/cjs/core/module-ref.js +84 -0
  17. package/dist/cjs/core/module-ref.js.map +1 -0
  18. package/dist/cjs/core/modules/container.js +305 -17
  19. package/dist/cjs/core/modules/container.js.map +1 -1
  20. package/dist/cjs/core/modules/module-container-factory.js +2 -2
  21. package/dist/cjs/core/modules/module-container-factory.js.map +1 -1
  22. package/dist/cjs/core/modules/module-container.js +54 -16
  23. package/dist/cjs/core/modules/module-container.js.map +1 -1
  24. package/dist/cjs/core/modules/module-token-factory.js.map +1 -1
  25. package/dist/cjs/core/modules/modules-container.js +43 -3
  26. package/dist/cjs/core/modules/modules-container.js.map +1 -1
  27. package/dist/cjs/core/nexus-applications.browser.js +57 -15
  28. package/dist/cjs/core/nexus-applications.browser.js.map +1 -1
  29. package/dist/cjs/core/nexus-applications.js +440 -82
  30. package/dist/cjs/core/nexus-applications.js.map +1 -1
  31. package/dist/cjs/core/nexus-applications.server.js +57 -15
  32. package/dist/cjs/core/nexus-applications.server.js.map +1 -1
  33. package/dist/cjs/core/resolver/providers-container.js.map +1 -1
  34. package/dist/cjs/core/resolver/resolution-context.js +62 -0
  35. package/dist/cjs/core/resolver/resolution-context.js.map +1 -0
  36. package/dist/cjs/core/resolver/resolver.js +523 -99
  37. package/dist/cjs/core/resolver/resolver.js.map +1 -1
  38. package/dist/cjs/decorators/inject.js +6 -3
  39. package/dist/cjs/decorators/inject.js.map +1 -1
  40. package/dist/cjs/decorators/injectable.js +0 -7
  41. package/dist/cjs/decorators/injectable.js.map +1 -1
  42. package/dist/cjs/decorators/{nsModule.js → module.js} +9 -7
  43. package/dist/cjs/decorators/module.js.map +1 -0
  44. package/dist/cjs/errors/bootstrap-error.js +47 -0
  45. package/dist/cjs/errors/bootstrap-error.js.map +1 -0
  46. package/dist/cjs/errors/child-errors.js +21 -0
  47. package/dist/cjs/errors/child-errors.js.map +1 -0
  48. package/dist/cjs/errors/index.js +24 -0
  49. package/dist/cjs/errors/index.js.map +1 -0
  50. package/dist/cjs/errors/injection-errors.js +25 -0
  51. package/dist/cjs/errors/injection-errors.js.map +1 -0
  52. package/dist/cjs/errors/lazy-module-errors.js +26 -0
  53. package/dist/cjs/errors/lazy-module-errors.js.map +1 -0
  54. package/dist/cjs/errors/provider-errors.js +95 -0
  55. package/dist/cjs/errors/provider-errors.js.map +1 -0
  56. package/dist/cjs/index.js +30 -6
  57. package/dist/cjs/index.js.map +1 -1
  58. package/dist/cjs/interfaces/index.js +1 -0
  59. package/dist/cjs/interfaces/index.js.map +1 -1
  60. package/dist/cjs/interfaces/modules/index.js +1 -0
  61. package/dist/cjs/interfaces/modules/index.js.map +1 -1
  62. package/dist/cjs/interfaces/modules/module-graph.interface.js +2 -0
  63. package/dist/cjs/interfaces/modules/module-graph.interface.js.map +1 -1
  64. package/dist/cjs/interfaces/modules/parent-link.interface.js +3 -0
  65. package/dist/cjs/interfaces/modules/parent-link.interface.js.map +1 -0
  66. package/dist/cjs/interfaces/on-module-destroy.interface.js +3 -0
  67. package/dist/cjs/interfaces/on-module-destroy.interface.js.map +1 -0
  68. package/dist/cjs/interfaces/scope.interface.js +2 -55
  69. package/dist/cjs/interfaces/scope.interface.js.map +1 -1
  70. package/dist/cjs/interfaces/validate-module-keys.js +2 -0
  71. package/dist/cjs/interfaces/validate-module-keys.js.map +1 -1
  72. package/dist/cjs/internal.js +9 -0
  73. package/dist/cjs/internal.js.map +1 -0
  74. package/dist/cjs/server.js +2 -2
  75. package/dist/cjs/server.js.map +1 -1
  76. package/dist/cjs/utils/forward-ref.js +14 -0
  77. package/dist/cjs/utils/forward-ref.js.map +1 -0
  78. package/dist/cjs/utils/helpers.js +14 -4
  79. package/dist/cjs/utils/helpers.js.map +1 -1
  80. package/dist/cjs/utils/lazy-module.js +33 -0
  81. package/dist/cjs/utils/lazy-module.js.map +1 -0
  82. package/dist/esm/browser.js +1 -1
  83. package/dist/esm/browser.js.map +1 -1
  84. package/dist/esm/core/child-module.js +29 -0
  85. package/dist/esm/core/child-module.js.map +1 -0
  86. package/dist/esm/core/graph/analyze-lazy-module.js +50 -0
  87. package/dist/esm/core/graph/analyze-lazy-module.js.map +1 -0
  88. package/dist/esm/core/graph/analyze-module.js +11 -0
  89. package/dist/esm/core/graph/analyze-module.js.map +1 -1
  90. package/dist/esm/core/graph/module-graph.js +686 -71
  91. package/dist/esm/core/graph/module-graph.js.map +1 -1
  92. package/dist/esm/core/injection/injection-context.js +25 -0
  93. package/dist/esm/core/injection/injection-context.js.map +1 -0
  94. package/dist/esm/core/lazy-module-loader.js +36 -0
  95. package/dist/esm/core/lazy-module-loader.js.map +1 -0
  96. package/dist/esm/core/module-ref.js +80 -0
  97. package/dist/esm/core/module-ref.js.map +1 -0
  98. package/dist/esm/core/modules/container.js +305 -17
  99. package/dist/esm/core/modules/container.js.map +1 -1
  100. package/dist/esm/core/modules/module-container-factory.js +2 -2
  101. package/dist/esm/core/modules/module-container-factory.js.map +1 -1
  102. package/dist/esm/core/modules/module-container.js +55 -17
  103. package/dist/esm/core/modules/module-container.js.map +1 -1
  104. package/dist/esm/core/modules/module-token-factory.js.map +1 -1
  105. package/dist/esm/core/modules/modules-container.js +43 -3
  106. package/dist/esm/core/modules/modules-container.js.map +1 -1
  107. package/dist/esm/core/nexus-applications.browser.js +55 -13
  108. package/dist/esm/core/nexus-applications.browser.js.map +1 -1
  109. package/dist/esm/core/nexus-applications.js +439 -81
  110. package/dist/esm/core/nexus-applications.js.map +1 -1
  111. package/dist/esm/core/nexus-applications.server.js +55 -13
  112. package/dist/esm/core/nexus-applications.server.js.map +1 -1
  113. package/dist/esm/core/resolver/providers-container.js.map +1 -1
  114. package/dist/esm/core/resolver/resolution-context.js +58 -0
  115. package/dist/esm/core/resolver/resolution-context.js.map +1 -0
  116. package/dist/esm/core/resolver/resolver.js +524 -100
  117. package/dist/esm/core/resolver/resolver.js.map +1 -1
  118. package/dist/esm/decorators/inject.js +6 -3
  119. package/dist/esm/decorators/inject.js.map +1 -1
  120. package/dist/esm/decorators/injectable.js +0 -7
  121. package/dist/esm/decorators/injectable.js.map +1 -1
  122. package/dist/esm/decorators/{nsModule.js → module.js} +8 -6
  123. package/dist/esm/decorators/module.js.map +1 -0
  124. package/dist/esm/errors/bootstrap-error.js +42 -0
  125. package/dist/esm/errors/bootstrap-error.js.map +1 -0
  126. package/dist/esm/errors/child-errors.js +17 -0
  127. package/dist/esm/errors/child-errors.js.map +1 -0
  128. package/dist/esm/errors/index.js +6 -0
  129. package/dist/esm/errors/index.js.map +1 -0
  130. package/dist/esm/errors/injection-errors.js +20 -0
  131. package/dist/esm/errors/injection-errors.js.map +1 -0
  132. package/dist/esm/errors/lazy-module-errors.js +21 -0
  133. package/dist/esm/errors/lazy-module-errors.js.map +1 -0
  134. package/dist/esm/errors/provider-errors.js +84 -0
  135. package/dist/esm/errors/provider-errors.js.map +1 -0
  136. package/dist/esm/index.js +9 -4
  137. package/dist/esm/index.js.map +1 -1
  138. package/dist/esm/interfaces/index.js +1 -0
  139. package/dist/esm/interfaces/index.js.map +1 -1
  140. package/dist/esm/interfaces/modules/index.js +1 -0
  141. package/dist/esm/interfaces/modules/index.js.map +1 -1
  142. package/dist/esm/interfaces/modules/module-graph.interface.js +2 -0
  143. package/dist/esm/interfaces/modules/module-graph.interface.js.map +1 -1
  144. package/dist/esm/interfaces/modules/parent-link.interface.js +2 -0
  145. package/dist/esm/interfaces/modules/parent-link.interface.js.map +1 -0
  146. package/dist/esm/interfaces/on-module-destroy.interface.js +2 -0
  147. package/dist/esm/interfaces/on-module-destroy.interface.js.map +1 -0
  148. package/dist/esm/interfaces/scope.interface.js +1 -55
  149. package/dist/esm/interfaces/scope.interface.js.map +1 -1
  150. package/dist/esm/interfaces/validate-module-keys.js +2 -0
  151. package/dist/esm/interfaces/validate-module-keys.js.map +1 -1
  152. package/dist/esm/internal.js +3 -0
  153. package/dist/esm/internal.js.map +1 -0
  154. package/dist/esm/server.js +1 -1
  155. package/dist/esm/server.js.map +1 -1
  156. package/dist/esm/utils/forward-ref.js +10 -0
  157. package/dist/esm/utils/forward-ref.js.map +1 -0
  158. package/dist/esm/utils/helpers.js +14 -4
  159. package/dist/esm/utils/helpers.js.map +1 -1
  160. package/dist/esm/utils/lazy-module.js +29 -0
  161. package/dist/esm/utils/lazy-module.js.map +1 -0
  162. package/dist/types/browser.d.ts +1 -1
  163. package/dist/types/core/child-module.d.ts +8 -0
  164. package/dist/types/core/graph/analyze-lazy-module.d.ts +28 -0
  165. package/dist/types/core/graph/analyze-module.d.ts +4 -2
  166. package/dist/types/core/graph/analyze-provider.d.ts +4 -4
  167. package/dist/types/core/graph/module-graph.d.ts +200 -7
  168. package/dist/types/core/graph/providers/analyze-class-provider.d.ts +1 -1
  169. package/dist/types/core/graph/providers/analyze-factory-provider.d.ts +2 -2
  170. package/dist/types/core/graph/providers/analyze-value-provider.d.ts +1 -1
  171. package/dist/types/core/injection/injection-context.d.ts +29 -0
  172. package/dist/types/core/lazy-module-loader.d.ts +17 -0
  173. package/dist/types/core/module-ref.d.ts +34 -0
  174. package/dist/types/core/modules/container.d.ts +134 -18
  175. package/dist/types/core/modules/module-container-factory.d.ts +3 -3
  176. package/dist/types/core/modules/module-container.d.ts +44 -5
  177. package/dist/types/core/modules/module-token-factory.d.ts +2 -2
  178. package/dist/types/core/modules/modules-container.d.ts +23 -4
  179. package/dist/types/core/nexus-applications.browser.d.ts +30 -8
  180. package/dist/types/core/nexus-applications.d.ts +219 -55
  181. package/dist/types/core/nexus-applications.server.d.ts +30 -8
  182. package/dist/types/core/resolver/providers-container.d.ts +2 -2
  183. package/dist/types/core/resolver/resolution-context.d.ts +22 -0
  184. package/dist/types/core/resolver/resolver.d.ts +122 -4
  185. package/dist/types/decorators/inject.d.ts +9 -5
  186. package/dist/types/decorators/injectable.d.ts +0 -7
  187. package/dist/types/decorators/{nsModule.d.ts → module.d.ts} +6 -5
  188. package/dist/types/errors/bootstrap-error.d.ts +6 -0
  189. package/dist/types/errors/child-errors.d.ts +10 -0
  190. package/dist/types/errors/index.d.ts +5 -0
  191. package/dist/types/errors/injection-errors.d.ts +11 -0
  192. package/dist/types/errors/lazy-module-errors.d.ts +12 -0
  193. package/dist/types/errors/provider-errors.d.ts +47 -0
  194. package/dist/types/index.d.ts +13 -4
  195. package/dist/types/interfaces/abstract.interface.d.ts +1 -3
  196. package/dist/types/interfaces/dynamic-module.interface.d.ts +7 -5
  197. package/dist/types/interfaces/index.d.ts +1 -0
  198. package/dist/types/interfaces/injection-token.interface.d.ts +1 -3
  199. package/dist/types/interfaces/module-metadata.interface.d.ts +12 -4
  200. package/dist/types/interfaces/module-types.interface.d.ts +21 -24
  201. package/dist/types/interfaces/modules/container.interface.d.ts +10 -4
  202. package/dist/types/interfaces/modules/index.d.ts +1 -0
  203. package/dist/types/interfaces/modules/module-container-factory.interface.d.ts +2 -2
  204. package/dist/types/interfaces/modules/module-graph.interface.d.ts +85 -12
  205. package/dist/types/interfaces/modules/module-token-factory.interface.d.ts +2 -2
  206. package/dist/types/interfaces/modules/modules-container.interface.d.ts +5 -4
  207. package/dist/types/interfaces/modules/parent-link.interface.d.ts +12 -0
  208. package/dist/types/interfaces/nexus-application.interface.d.ts +49 -6
  209. package/dist/types/interfaces/on-module-destroy.interface.d.ts +3 -0
  210. package/dist/types/interfaces/plugins/scanner-plugin.interface.d.ts +1 -1
  211. package/dist/types/interfaces/scope.interface.d.ts +1 -54
  212. package/dist/types/interfaces/validate-module-keys.d.ts +1 -0
  213. package/dist/types/internal.d.ts +3 -0
  214. package/dist/types/server.d.ts +1 -1
  215. package/dist/types/utils/forward-ref.d.ts +5 -0
  216. package/dist/types/utils/helpers.d.ts +8 -8
  217. package/dist/types/utils/lazy-module.d.ts +20 -0
  218. package/package.json +23 -7
  219. package/dist/cjs/decorators/nsModule.js.map +0 -1
  220. package/dist/esm/decorators/nsModule.js.map +0 -1
  221. package/dist/tsconfig.cjs.tsbuildinfo +0 -1
  222. package/dist/tsconfig.esm.tsbuildinfo +0 -1
@@ -1,4 +1,14 @@
1
- import type { ContainerInterface, DynamicModule, HashUtilInterface, InjectionToken, Module, ModuleContainerInterface, ModuleGraphInterface } from "../../interfaces";
1
+ import "reflect-metadata";
2
+ import type { ContainerInterface, DynamicModule, GraphSegment, HashUtilInterface, LazyModule, ModuleContainerInterface, ModuleGraphInterface, ParentLink, ProviderToken, Type, UnloadResult } from "../../interfaces";
3
+ /**
4
+ * Called by `Container.unload` with the module tokens about to be destroyed.
5
+ * Reports how many child applications it closed and, if any of them failed
6
+ * to close, the error to rethrow once the unload has finished.
7
+ */
8
+ export type UnloadingHook = (destroyedModules: string[]) => Promise<{
9
+ closed: number;
10
+ error?: unknown;
11
+ }>;
2
12
  /**
3
13
  * Container is the core IoC (Inversion of Control) container that manages
4
14
  * modules, providers, and dependency injection.
@@ -13,7 +23,7 @@ import type { ContainerInterface, DynamicModule, HashUtilInterface, InjectionTok
13
23
  * ```typescript
14
24
  * const container = new Container(hashUtils);
15
25
  * await container.run(AppModule);
16
- * const service = await container.get(MyService);
26
+ * const service = container.get(MyService);
17
27
  * ```
18
28
  */
19
29
  export declare class Container implements ContainerInterface {
@@ -21,6 +31,23 @@ export declare class Container implements ContainerInterface {
21
31
  private readonly modulesContainer;
22
32
  private _graph;
23
33
  private moduleGraphResolver;
34
+ /** The parent chain of a child container; kept for runtime resolution. */
35
+ private link;
36
+ private closed;
37
+ private readonly segments;
38
+ /**
39
+ * Root module token of every currently loaded segment, by ref id. Used
40
+ * to compute `protectedRoots` for `unload`; set once a segment's
41
+ * compile succeeds, cleared once it is unloaded.
42
+ */
43
+ private readonly loadedSegments;
44
+ /**
45
+ * Tail of the segment compilation chain. Loader functions run in parallel,
46
+ * but the graph mutation that follows each of them runs one at a time.
47
+ */
48
+ private compileQueue;
49
+ /** See `onUnloading`. */
50
+ private unloadingHook;
24
51
  /**
25
52
  * Creates a new Container instance.
26
53
  *
@@ -43,7 +70,7 @@ export declare class Container implements ContainerInterface {
43
70
  * await container.addModule(DatabaseModule.forRoot({ host: 'localhost' }));
44
71
  * ```
45
72
  */
46
- addModule(module: Module | DynamicModule): Promise<ModuleContainerInterface>;
73
+ addModule(module: Type | DynamicModule): Promise<ModuleContainerInterface>;
47
74
  /**
48
75
  * Replaces an existing module with a new module.
49
76
  *
@@ -59,7 +86,7 @@ export declare class Container implements ContainerInterface {
59
86
  * await container.replaceModule(OldDatabaseModule, NewDatabaseModule);
60
87
  * ```
61
88
  */
62
- replaceModule(moduleToReplace: Module, newModule: Module): Promise<ModuleContainerInterface>;
89
+ replaceModule(moduleToReplace: Type, newModule: Type): Promise<ModuleContainerInterface>;
63
90
  /**
64
91
  * Retrieves a module container by its module class.
65
92
  *
@@ -71,27 +98,46 @@ export declare class Container implements ContainerInterface {
71
98
  * const moduleContainer = await container.getModule(DatabaseModule);
72
99
  * ```
73
100
  */
74
- getModule(module: Module): Promise<ModuleContainerInterface | undefined>;
101
+ getModule(module: Type): Promise<ModuleContainerInterface | undefined>;
102
+ /**
103
+ * True iff the graph has a provider node for the token.
104
+ */
105
+ hasProvider(token: ProviderToken): boolean;
75
106
  /**
76
- * Resolves and returns an instance of a provider by its injection token.
107
+ * Synchronously returns an already-created singleton.
77
108
  *
78
- * This is the main method for retrieving dependencies from the container.
79
- * The instance is created according to its scope:
80
- * - Singleton: Same instance returned every time
81
- * - Request: New instance for each get() call
82
- * - Transient: New instance every time, even within the same dependency tree
109
+ * @throws {ProviderNotFoundError} If no provider has this token
110
+ * @throws {ProviderScopeError} If the provider is Transient
111
+ * @throws {ProviderNotInstantiatedError} If the singleton is not created yet
83
112
  *
84
- * @template T - The type of the provider to resolve
85
- * @param token - The injection token (class, string, or symbol)
86
- * @returns A promise that resolves to the provider instance, or undefined if not found
113
+ * @example
114
+ * ```typescript
115
+ * await container.run(AppModule);
116
+ * const userService = container.get(UserService);
117
+ * ```
118
+ */
119
+ get<T>(token: ProviderToken<T>): T;
120
+ /**
121
+ * Resolves an instance of a provider, creating it according to its scope.
122
+ *
123
+ * @throws {ProviderNotFoundError} If no provider has this token
87
124
  *
88
125
  * @example
89
126
  * ```typescript
90
- * const userService = await container.get(UserService);
91
- * const config = await container.get('CONFIG');
127
+ * const userService = await container.resolve(UserService);
92
128
  * ```
93
129
  */
94
- get<T>(token: InjectionToken): Promise<T | undefined>;
130
+ resolve<T>(token: ProviderToken<T>): Promise<T>;
131
+ /**
132
+ * Pre-instantiates every singleton provider named by `tokens` (other
133
+ * tokens are skipped). Uses the resolver directly, without the closed
134
+ * guard, so a load that was already in flight when `close()` started can
135
+ * still finish its warm-up; those singletons are destroyed by the
136
+ * teardown that follows.
137
+ *
138
+ * @throws {ContainerNotCompiledError} If run() has not been called yet
139
+ */
140
+ instantiateSingletons(tokens: Iterable<ProviderToken>): Promise<void>;
95
141
  /**
96
142
  * Initializes and runs the container with the specified root module.
97
143
  *
@@ -104,6 +150,10 @@ export declare class Container implements ContainerInterface {
104
150
  * This method must be called before using get() to resolve dependencies.
105
151
  *
106
152
  * @param rootModule - The root module of the application
153
+ * @param internalModules - Framework-provided global modules compiled before
154
+ * the user root, so their exports are visible to every user module
155
+ * @param options.link - The parent chain of a child container. Dependencies
156
+ * not visible locally but provided by the link compile as external edges.
107
157
  * @returns A promise that resolves when initialization is complete
108
158
  * @throws {Error} If there are circular dependencies or missing providers
109
159
  *
@@ -114,7 +164,52 @@ export declare class Container implements ContainerInterface {
114
164
  * // Now you can use container.get() to resolve dependencies
115
165
  * ```
116
166
  */
117
- run(rootModule: Module): Promise<void>;
167
+ run(rootModule: Type | DynamicModule, internalModules?: DynamicModule[], options?: {
168
+ link?: ParentLink;
169
+ }): Promise<void>;
170
+ /**
171
+ * Loads a lazy module into this container: runs its loader, registers the
172
+ * module and compiles only the new part of the graph. Idempotent per ref;
173
+ * concurrent calls share one in-flight load. A failed load is not cached,
174
+ * so the caller may retry.
175
+ *
176
+ * @param lazyModule - The lazy module reference, created via `lazy()`
177
+ * @returns A promise that resolves to the graph segment added by this load
178
+ * @throws {ContainerNotCompiledError} If run() has not been called yet
179
+ * @throws {LazyModuleLoadError} If the loader rejects or does not return a @Module() class
180
+ * @throws {LazyModuleGraphError} If the loaded module fails to compile
181
+ */
182
+ load(lazyModule: LazyModule): Promise<GraphSegment>;
183
+ /**
184
+ * Runs `fn` after every previously enqueued task has settled, so segment
185
+ * registration and compilation never interleave. A rejected task does not
186
+ * break the chain for the tasks behind it.
187
+ */
188
+ private enqueueCompile;
189
+ private loadSegment;
190
+ /**
191
+ * Unloads a previously loaded lazy segment: destroys every singleton and
192
+ * module nothing else still needs, and leaves the rest untouched (a
193
+ * shared module, a `@Global()` module another segment depends on, a
194
+ * nested lazy module loaded from inside this one). Runs on the same
195
+ * compile queue as `load`, so it never interleaves with a concurrent
196
+ * load or unload of a different ref. Waits for an in-flight load of the
197
+ * same ref to settle first. A ref that was never loaded is a no-op.
198
+ * Concurrent `unload()` calls for the *same* ref are also safe, but only
199
+ * because `ModuleGraph.unloadSegment` is idempotent (a second call
200
+ * against an already-unloaded placeholder is a no-op) — `Container.unload`
201
+ * itself does not enforce this, so a future change to `unloadSegment`
202
+ * must preserve that idempotency or this guarantee silently breaks.
203
+ */
204
+ unload(lazyModule: LazyModule): Promise<UnloadResult>;
205
+ /**
206
+ * Registers the hook `unload` calls once the graph has dropped a segment
207
+ * and before that segment's providers are destroyed, with the tokens of
208
+ * the modules being destroyed. The application closes the child
209
+ * applications those modules declared there. One hook per container; a
210
+ * later call replaces it.
211
+ */
212
+ onUnloading(hook: UnloadingHook): void;
118
213
  /**
119
214
  * Gets the dependency graph.
120
215
  *
@@ -151,4 +246,25 @@ export declare class Container implements ContainerInterface {
151
246
  * ```
152
247
  */
153
248
  get errors(): import("@nexus-ioc/shared").GraphError[];
249
+ /** Whether run() has built the graph, so get()/resolve() can be used. */
250
+ get isCompiled(): boolean;
251
+ /** Whether the container has been closed (or is closing). */
252
+ get isClosed(): boolean;
253
+ private assertOpen;
254
+ /**
255
+ * Synchronously marks the container closed: every later public
256
+ * `get`/`resolve`/`load`/`unload` call throws `ContainerClosedError`.
257
+ * Work already in flight (a load past its guard, its singleton warm-up)
258
+ * is not interrupted. `close()` calls this too; callers that need the
259
+ * flag set before they drain their own work call it first.
260
+ */
261
+ markClosed(): void;
262
+ /**
263
+ * Closes the container and cleans up resources: marks it closed, waits
264
+ * for in-flight segment loads, then destroys every created provider on
265
+ * the compile queue.
266
+ *
267
+ * @returns A promise that resolves when the container is closed
268
+ */
269
+ close(): Promise<void>;
154
270
  }
@@ -1,9 +1,9 @@
1
1
  import "reflect-metadata";
2
- import type { ContainerBaseInterface, DynamicModule, Module, ModuleContainerFactoryInterface, ModuleContainerInterface, ModuleTokenFactoryInterface } from "../../interfaces";
2
+ import type { ContainerBaseInterface, DynamicModule, ModuleContainerFactoryInterface, ModuleContainerInterface, ModuleTokenFactoryInterface, Type } from "../../interfaces";
3
3
  export declare class ModuleContainerFactory implements ModuleContainerFactoryInterface {
4
4
  private readonly moduleTokenFactory;
5
5
  constructor(moduleTokenFactory: ModuleTokenFactoryInterface);
6
- create(module: Module | DynamicModule, container: ContainerBaseInterface): Promise<ModuleContainerInterface>;
7
- getModuleToken(module: Module | DynamicModule): Promise<string>;
6
+ create(module: Type | DynamicModule, container: ContainerBaseInterface, resolveReplacement?: (module: Type) => Type): Promise<ModuleContainerInterface>;
7
+ getModuleToken(module: Type | DynamicModule): Promise<string>;
8
8
  getModuleContainerImports(module: ModuleContainerInterface): Promise<ModuleContainerInterface[]>;
9
9
  }
@@ -1,16 +1,55 @@
1
1
  import "reflect-metadata";
2
- import type { ContainerBaseInterface, DynamicModule, InjectionToken, Module, ModuleContainerInterface, Provider } from "../../interfaces";
2
+ import type { ContainerBaseInterface, DynamicModule, GetOptions, LazyModule, ModuleContainerInterface, Provider, ProviderToken, Type } from "../../interfaces";
3
3
  export declare class ModuleContainer implements ModuleContainerInterface {
4
4
  private readonly _metatype;
5
5
  private readonly container;
6
+ private readonly resolveReplacement;
6
7
  private _token;
7
- constructor(_metatype: Module | DynamicModule, container: ContainerBaseInterface);
8
+ constructor(_metatype: Type | DynamicModule, container: ContainerBaseInterface, resolveReplacement?: (module: Type) => Type);
8
9
  get token(): string;
9
10
  set token(value: string);
10
- get metatype(): Module | DynamicModule;
11
+ get metatype(): DynamicModule | Type<any>;
12
+ private get declaredImports();
13
+ private _resolvedImports;
14
+ get resolvedImports(): ModuleContainerInterface[] | undefined;
11
15
  get imports(): Promise<ModuleContainerInterface[]>;
16
+ get lazyImports(): LazyModule[];
17
+ /**
18
+ * Children declared by the module class's `@Module` decorator. A dynamic
19
+ * module literal cannot declare children, but one built from a class that
20
+ * declares them (`forX()`, extra child providers) keeps them.
21
+ */
22
+ get children(): readonly (Type | LazyModule)[];
12
23
  get providers(): Provider[];
13
- get exports(): InjectionToken[];
14
- get<T>(token: InjectionToken): Promise<T | undefined>;
24
+ get exports(): ProviderToken[];
25
+ /**
26
+ * Synchronously returns an already-created singleton, with the same
27
+ * contract as `Test.get()`.
28
+ *
29
+ * @throws {ProviderNotFoundError} If no provider has this token (unless optional)
30
+ * @throws {ProviderScopeError} If the provider is Transient; use resolve()
31
+ * @throws {ProviderNotInstantiatedError} If the singleton is not created yet; use resolve()
32
+ */
33
+ get<T>(token: ProviderToken<T>): T;
34
+ get<T>(token: ProviderToken<T>, options: {
35
+ optional: true;
36
+ }): T | undefined;
37
+ get<T>(token: ProviderToken<T>, options: {
38
+ optional?: false;
39
+ }): T;
40
+ get<T>(token: ProviderToken<T>, options: GetOptions): T | undefined;
41
+ /**
42
+ * Resolves a provider asynchronously, creating it according to its scope.
43
+ *
44
+ * @throws {ProviderNotFoundError} If no provider has this token (unless optional)
45
+ */
46
+ resolve<T>(token: ProviderToken<T>): Promise<T>;
47
+ resolve<T>(token: ProviderToken<T>, options: {
48
+ optional: true;
49
+ }): Promise<T | undefined>;
50
+ resolve<T>(token: ProviderToken<T>, options: {
51
+ optional?: false;
52
+ }): Promise<T>;
53
+ resolve<T>(token: ProviderToken<T>, options: GetOptions): Promise<T | undefined>;
15
54
  get errors(): import("@nexus-ioc/shared").GraphError[];
16
55
  }
@@ -1,11 +1,11 @@
1
- import type { DynamicModule, HashUtilInterface, Module, ModuleTokenFactoryInterface } from "../../interfaces";
1
+ import type { DynamicModule, HashUtilInterface, ModuleTokenFactoryInterface, Type } from "../../interfaces";
2
2
  export declare class ModuleTokenFactory implements ModuleTokenFactoryInterface {
3
3
  private readonly hashUtils;
4
4
  private readonly moduleTokenCache;
5
5
  private readonly moduleTokens;
6
6
  private readonly moduleIdsCache;
7
7
  constructor(hashUtils: HashUtilInterface);
8
- create(metatype: Module | DynamicModule): Promise<string>;
8
+ create(metatype: Type | DynamicModule): Promise<string>;
9
9
  private getStaticModuleToken;
10
10
  private getMetatypeId;
11
11
  private getModuleName;
@@ -1,16 +1,35 @@
1
1
  import "reflect-metadata";
2
- import { type ContainerInterface, type DynamicModule, type HashUtilInterface, type Module, type ModuleContainerInterface, type ModulesContainerInterface } from "../../interfaces";
2
+ import { type ContainerInterface, type DynamicModule, type HashUtilInterface, type ModuleContainerInterface, type ModulesContainerInterface, type Type } from "../../interfaces";
3
3
  export type Token = string;
4
4
  export declare class ModulesContainer implements ModulesContainerInterface {
5
5
  private readonly hashUtils;
6
6
  private readonly container;
7
7
  private readonly containers;
8
+ /**
9
+ * Modules registered through `replaceModule`, keyed by the replaced class.
10
+ * Every lookup of a replaced module (`addModule`, `getModule`) is redirected
11
+ * to its replacement, even when the replaced module was not registered yet.
12
+ * Modules that were not replaced are never affected. This holds for
13
+ * everything this container adds later too, lazy modules included.
14
+ */
15
+ private readonly replacements;
8
16
  private readonly moduleTokenFactory;
9
17
  private readonly moduleContainerFactory;
10
18
  constructor(hashUtils: HashUtilInterface, container: ContainerInterface);
11
- addModule(module: Module | DynamicModule): Promise<ModuleContainerInterface>;
12
- getModule(module: Module | DynamicModule): ModuleContainerInterface | undefined;
13
- replaceModule(moduleToReplace: Module, newModule: Module): Promise<ModuleContainerInterface>;
19
+ addModule(module: Type | DynamicModule): Promise<ModuleContainerInterface>;
20
+ getModule(module: Type | DynamicModule): ModuleContainerInterface | undefined;
21
+ removeModule(token: Token): void;
22
+ replaceModule(moduleToReplace: Type, newModule: Type): Promise<ModuleContainerInterface>;
23
+ /**
24
+ * Maps a module through the replacements. The chain is followed
25
+ * (`A -> B -> C` gives `C`) and stops at a cycle (`A -> B`, `B -> A`).
26
+ *
27
+ * A `DynamicModule` whose `module` class is replaced is swapped for the
28
+ * replacement class used as a plain static module: the replacement is a
29
+ * class, so the dynamic module's own providers, imports and exports (meant
30
+ * for the replaced class) are dropped.
31
+ */
32
+ private applyReplacement;
14
33
  private setModule;
15
34
  private getModuleFromCache;
16
35
  }
@@ -1,21 +1,43 @@
1
- import type { InjectionToken, Module, NexusApplicationInterface, ScannerPluginInterface } from "../interfaces";
1
+ import type { CreateChildOptions, DynamicModule, GetOptions, LazyModule, NexusApplicationInterface, ProviderToken, ScannerPluginInterface, Type, UnloadResult } from "../interfaces";
2
+ import { ModuleRef } from "./module-ref";
2
3
  /**
3
4
  * @deprecated
4
5
  * It will be removed in version 1.0.0.
5
- * these classes work the same way. For the new behavior, use @NexusApplications
6
+ * these classes work the same way. For the new behavior, use @NexusApplication
6
7
  */
7
- export declare class NexusApplicationsBrowser implements NexusApplicationInterface {
8
+ export declare class NexusApplicationBrowser implements NexusApplicationInterface {
8
9
  private readonly rootModule;
9
10
  private readonly hashUtil;
10
11
  private readonly scannerPlugins;
11
12
  private readonly container;
12
- private _parentContainer;
13
+ private closePromise;
13
14
  private constructor();
14
- static create(rootModule: Module): NexusApplicationsBrowser;
15
+ static create(rootModule: Type): NexusApplicationBrowser;
15
16
  bootstrap(): Promise<this>;
16
17
  addScannerPlugin(scanner: ScannerPluginInterface | ScannerPluginInterface[]): this;
17
- get<T>(token: InjectionToken): Promise<T | undefined>;
18
+ get<T>(token: ProviderToken<T>): T;
19
+ get<T>(token: ProviderToken<T>, options: {
20
+ optional: true;
21
+ }): T | undefined;
22
+ get<T>(token: ProviderToken<T>, options: {
23
+ optional?: false;
24
+ }): T;
25
+ get<T>(token: ProviderToken<T>, options: GetOptions): T | undefined;
26
+ resolve<T>(token: ProviderToken<T>): Promise<T>;
27
+ resolve<T>(token: ProviderToken<T>, options: {
28
+ optional: true;
29
+ }): Promise<T | undefined>;
30
+ resolve<T>(token: ProviderToken<T>, options: {
31
+ optional?: false;
32
+ }): Promise<T>;
33
+ resolve<T>(token: ProviderToken<T>, options: GetOptions): Promise<T | undefined>;
18
34
  get errors(): import("@nexus-ioc/shared").GraphError[];
19
- async(): this;
20
- setParent(parentContainer: NexusApplicationInterface): this;
35
+ load(lazyModule: LazyModule): Promise<ModuleRef>;
36
+ unload(ref: ModuleRef): Promise<UnloadResult>;
37
+ lazy(): this;
38
+ close(): Promise<void>;
39
+ get isClosed(): boolean;
40
+ private assertOpen;
41
+ private assertUsable;
42
+ createChild(_child: Type | DynamicModule | LazyModule, _options?: CreateChildOptions): Promise<NexusApplicationInterface>;
21
43
  }