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