1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.NestApplicationContext = void 0;
|
4 | const common_1 = require("@nestjs/common");
|
5 | const interfaces_1 = require("@nestjs/common/interfaces");
|
6 | const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
|
7 | const iterare_1 = require("iterare");
|
8 | const constants_1 = require("./constants");
|
9 | const invalid_class_scope_exception_1 = require("./errors/exceptions/invalid-class-scope.exception");
|
10 | const unknown_element_exception_1 = require("./errors/exceptions/unknown-element.exception");
|
11 | const unknown_module_exception_1 = require("./errors/exceptions/unknown-module.exception");
|
12 | const context_id_factory_1 = require("./helpers/context-id-factory");
|
13 | const hooks_1 = require("./hooks");
|
14 | const compiler_1 = require("./injector/compiler");
|
15 | const injector_1 = require("./injector/injector");
|
16 | const instance_links_host_1 = require("./injector/instance-links-host");
|
17 |
|
18 |
|
19 |
|
20 | class NestApplicationContext {
|
21 | constructor(container, scope = new Array(), contextModule = null) {
|
22 | this.container = container;
|
23 | this.scope = scope;
|
24 | this.contextModule = contextModule;
|
25 | this.isInitialized = false;
|
26 | this.injector = new injector_1.Injector();
|
27 | this.activeShutdownSignals = new Array();
|
28 | this.moduleCompiler = new compiler_1.ModuleCompiler();
|
29 | }
|
30 | get instanceLinksHost() {
|
31 | if (!this._instanceLinksHost) {
|
32 | this._instanceLinksHost = new instance_links_host_1.InstanceLinksHost(this.container);
|
33 | }
|
34 | return this._instanceLinksHost;
|
35 | }
|
36 | selectContextModule() {
|
37 | const modules = this.container.getModules().values();
|
38 | this.contextModule = modules.next().value;
|
39 | }
|
40 | select(moduleType) {
|
41 | const modulesContainer = this.container.getModules();
|
42 | const contextModuleCtor = this.contextModule.metatype;
|
43 | const scope = this.scope.concat(contextModuleCtor);
|
44 | const moduleTokenFactory = this.container.getModuleTokenFactory();
|
45 | const { type, dynamicMetadata } = this.moduleCompiler.extractMetadata(moduleType);
|
46 | const token = moduleTokenFactory.create(type, dynamicMetadata);
|
47 | const selectedModule = modulesContainer.get(token);
|
48 | if (!selectedModule) {
|
49 | throw new unknown_module_exception_1.UnknownModuleException();
|
50 | }
|
51 | return new NestApplicationContext(this.container, scope, selectedModule);
|
52 | }
|
53 | get(typeOrToken, options = { strict: false }) {
|
54 | return !(options && options.strict)
|
55 | ? this.find(typeOrToken)
|
56 | : this.find(typeOrToken, this.contextModule);
|
57 | }
|
58 | resolve(typeOrToken, contextId = context_id_factory_1.createContextId(), options = { strict: false }) {
|
59 | return this.resolvePerContext(typeOrToken, this.contextModule, contextId, options);
|
60 | }
|
61 | registerRequestByContextId(request, contextId) {
|
62 | this.container.registerRequestProvider(request, contextId);
|
63 | }
|
64 | |
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 | async init() {
|
71 | if (this.isInitialized) {
|
72 | return this;
|
73 | }
|
74 | await this.callInitHook();
|
75 | await this.callBootstrapHook();
|
76 | this.isInitialized = true;
|
77 | return this;
|
78 | }
|
79 | async close() {
|
80 | await this.callDestroyHook();
|
81 | await this.callBeforeShutdownHook();
|
82 | await this.dispose();
|
83 | await this.callShutdownHook();
|
84 | this.unsubscribeFromProcessSignals();
|
85 | }
|
86 | useLogger(logger) {
|
87 | common_1.Logger.overrideLogger(logger);
|
88 | }
|
89 | flushLogs() {
|
90 | common_1.Logger.flush();
|
91 | }
|
92 | |
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 | enableShutdownHooks(signals = []) {
|
102 | if (shared_utils_1.isEmpty(signals)) {
|
103 | signals = Object.keys(common_1.ShutdownSignal).map((key) => common_1.ShutdownSignal[key]);
|
104 | }
|
105 | else {
|
106 |
|
107 |
|
108 | signals = Array.from(new Set(signals));
|
109 | }
|
110 | signals = iterare_1.iterate(signals)
|
111 | .map((signal) => signal.toString().toUpperCase().trim())
|
112 |
|
113 | .filter(signal => !this.activeShutdownSignals.includes(signal))
|
114 | .toArray();
|
115 | this.listenToShutdownSignals(signals);
|
116 | return this;
|
117 | }
|
118 | async dispose() {
|
119 |
|
120 |
|
121 | return Promise.resolve();
|
122 | }
|
123 | |
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 | listenToShutdownSignals(signals) {
|
130 | const cleanup = async (signal) => {
|
131 | var _a;
|
132 | try {
|
133 | signals.forEach(sig => process.removeListener(sig, cleanup));
|
134 | await this.callDestroyHook();
|
135 | await this.callBeforeShutdownHook(signal);
|
136 | await this.dispose();
|
137 | await this.callShutdownHook(signal);
|
138 | process.kill(process.pid, signal);
|
139 | }
|
140 | catch (err) {
|
141 | common_1.Logger.error(constants_1.MESSAGES.ERROR_DURING_SHUTDOWN, (_a = err) === null || _a === void 0 ? void 0 : _a.stack, NestApplicationContext.name);
|
142 | process.exit(1);
|
143 | }
|
144 | };
|
145 | this.shutdownCleanupRef = cleanup;
|
146 | signals.forEach((signal) => {
|
147 | this.activeShutdownSignals.push(signal);
|
148 | process.on(signal, cleanup);
|
149 | });
|
150 | }
|
151 | |
152 |
|
153 |
|
154 | unsubscribeFromProcessSignals() {
|
155 | if (!this.shutdownCleanupRef) {
|
156 | return;
|
157 | }
|
158 | this.activeShutdownSignals.forEach(signal => {
|
159 | process.removeListener(signal, this.shutdownCleanupRef);
|
160 | });
|
161 | }
|
162 | |
163 |
|
164 |
|
165 |
|
166 | async callInitHook() {
|
167 | const modulesSortedByDistance = this.getModulesSortedByDistance();
|
168 | for (const module of modulesSortedByDistance) {
|
169 | await hooks_1.callModuleInitHook(module);
|
170 | }
|
171 | }
|
172 | |
173 |
|
174 |
|
175 |
|
176 | async callDestroyHook() {
|
177 | const modulesSortedByDistance = this.getModulesSortedByDistance();
|
178 | for (const module of modulesSortedByDistance) {
|
179 | await hooks_1.callModuleDestroyHook(module);
|
180 | }
|
181 | }
|
182 | |
183 |
|
184 |
|
185 |
|
186 | async callBootstrapHook() {
|
187 | const modulesSortedByDistance = this.getModulesSortedByDistance();
|
188 | for (const module of modulesSortedByDistance) {
|
189 | await hooks_1.callModuleBootstrapHook(module);
|
190 | }
|
191 | }
|
192 | |
193 |
|
194 |
|
195 |
|
196 | async callShutdownHook(signal) {
|
197 | const modulesSortedByDistance = this.getModulesSortedByDistance();
|
198 | for (const module of modulesSortedByDistance) {
|
199 | await hooks_1.callAppShutdownHook(module, signal);
|
200 | }
|
201 | }
|
202 | |
203 |
|
204 |
|
205 |
|
206 | async callBeforeShutdownHook(signal) {
|
207 | const modulesSortedByDistance = this.getModulesSortedByDistance();
|
208 | for (const module of modulesSortedByDistance) {
|
209 | await hooks_1.callBeforeAppShutdownHook(module, signal);
|
210 | }
|
211 | }
|
212 | find(typeOrToken, contextModule) {
|
213 | const moduleId = contextModule && contextModule.id;
|
214 | const { wrapperRef } = this.instanceLinksHost.get(typeOrToken, moduleId);
|
215 | if (wrapperRef.scope === interfaces_1.Scope.REQUEST ||
|
216 | wrapperRef.scope === interfaces_1.Scope.TRANSIENT) {
|
217 | throw new invalid_class_scope_exception_1.InvalidClassScopeException(typeOrToken);
|
218 | }
|
219 | return wrapperRef.instance;
|
220 | }
|
221 | async resolvePerContext(typeOrToken, contextModule, contextId, options) {
|
222 | const isStrictModeEnabled = options && options.strict;
|
223 | const instanceLink = isStrictModeEnabled
|
224 | ? this.instanceLinksHost.get(typeOrToken, contextModule.id)
|
225 | : this.instanceLinksHost.get(typeOrToken);
|
226 | const { wrapperRef, collection } = instanceLink;
|
227 | if (wrapperRef.isDependencyTreeStatic() && !wrapperRef.isTransient) {
|
228 | return this.get(typeOrToken, options);
|
229 | }
|
230 | const ctorHost = wrapperRef.instance || { constructor: typeOrToken };
|
231 | const instance = await this.injector.loadPerContext(ctorHost, wrapperRef.host, collection, contextId);
|
232 | if (!instance) {
|
233 | throw new unknown_element_exception_1.UnknownElementException();
|
234 | }
|
235 | return instance;
|
236 | }
|
237 | getModulesSortedByDistance() {
|
238 | if (this._moduleRefsByDistance) {
|
239 | return this._moduleRefsByDistance;
|
240 | }
|
241 | const modulesContainer = this.container.getModules();
|
242 | const compareFn = (a, b) => b.distance - a.distance;
|
243 | this._moduleRefsByDistance = Array.from(modulesContainer.values()).sort(compareFn);
|
244 | return this._moduleRefsByDistance;
|
245 | }
|
246 | }
|
247 | exports.NestApplicationContext = NestApplicationContext;
|