UNPKG

8.41 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const common_1 = require("@nestjs/common");
4const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
5const constants_1 = require("./constants");
6const unknown_element_exception_1 = require("./errors/exceptions/unknown-element.exception");
7const unknown_module_exception_1 = require("./errors/exceptions/unknown-module.exception");
8const helpers_1 = require("./helpers");
9const hooks_1 = require("./hooks");
10const container_scanner_1 = require("./injector/container-scanner");
11const injector_1 = require("./injector/injector");
12const iterare_1 = require("iterare");
13/**
14 * @publicApi
15 */
16class NestApplicationContext {
17 constructor(container, scope = new Array(), contextModule = null) {
18 this.container = container;
19 this.scope = scope;
20 this.contextModule = contextModule;
21 this.isInitialized = false;
22 this.injector = new injector_1.Injector();
23 this.activeShutdownSignals = new Array();
24 this.containerScanner = new container_scanner_1.ContainerScanner(container);
25 }
26 selectContextModule() {
27 const modules = this.container.getModules().values();
28 this.contextModule = modules.next().value;
29 }
30 select(moduleType) {
31 const modules = this.container.getModules();
32 const moduleMetatype = this.contextModule.metatype;
33 const scope = this.scope.concat(moduleMetatype);
34 const moduleTokenFactory = this.container.getModuleTokenFactory();
35 const token = moduleTokenFactory.create(moduleType);
36 const selectedModule = modules.get(token);
37 if (!selectedModule) {
38 throw new unknown_module_exception_1.UnknownModuleException();
39 }
40 return new NestApplicationContext(this.container, scope, selectedModule);
41 }
42 get(typeOrToken, options = { strict: false }) {
43 if (!(options && options.strict)) {
44 return this.find(typeOrToken);
45 }
46 return this.findInstanceByToken(typeOrToken, this.contextModule);
47 }
48 resolve(typeOrToken, contextId = helpers_1.createContextId(), options = { strict: false }) {
49 return this.resolvePerContext(typeOrToken, this.contextModule, contextId, options);
50 }
51 /**
52 * Initalizes the Nest application.
53 * Calls the Nest lifecycle events.
54 *
55 * @returns {Promise<this>} The NestApplicationContext instance as Promise
56 */
57 async init() {
58 if (this.isInitialized) {
59 return this;
60 }
61 await this.callInitHook();
62 await this.callBootstrapHook();
63 this.isInitialized = true;
64 return this;
65 }
66 async close() {
67 await this.callDestroyHook();
68 await this.callBeforeShutdownHook();
69 await this.dispose();
70 await this.callShutdownHook();
71 await this.unsubscribeFromProcessSignals();
72 }
73 useLogger(logger) {
74 common_1.Logger.overrideLogger(logger);
75 }
76 /**
77 * Enables the usage of shutdown hooks. Will call the
78 * `onApplicationShutdown` function of a provider if the
79 * process receives a shutdown signal.
80 *
81 * @param {ShutdownSignal[]} [signals=[]] The system signals it should listen to
82 *
83 * @returns {this} The Nest application context instance
84 */
85 enableShutdownHooks(signals = []) {
86 if (shared_utils_1.isEmpty(signals)) {
87 signals = Object.keys(common_1.ShutdownSignal).map((key) => common_1.ShutdownSignal[key]);
88 }
89 else {
90 // given signals array should be unique because
91 // process shouldn't listen to the same signal more than once.
92 signals = Array.from(new Set(signals));
93 }
94 signals = iterare_1.iterate(signals)
95 .map((signal) => signal
96 .toString()
97 .toUpperCase()
98 .trim())
99 // filter out the signals which is already listening to
100 .filter(signal => !this.activeShutdownSignals.includes(signal))
101 .toArray();
102 this.listenToShutdownSignals(signals);
103 return this;
104 }
105 async dispose() {
106 // Nest application context has no server
107 // to dispose, therefore just call a noop
108 return Promise.resolve();
109 }
110 /**
111 * Listens to shutdown signals by listening to
112 * process events
113 *
114 * @param {string[]} signals The system signals it should listen to
115 */
116 listenToShutdownSignals(signals) {
117 const cleanup = async (signal) => {
118 try {
119 signals.forEach(sig => process.removeListener(sig, cleanup));
120 await this.callDestroyHook();
121 await this.callBeforeShutdownHook(signal);
122 await this.dispose();
123 await this.callShutdownHook(signal);
124 process.kill(process.pid, signal);
125 }
126 catch (err) {
127 common_1.Logger.error(constants_1.MESSAGES.ERROR_DURING_SHUTDOWN, err.stack, NestApplicationContext.name);
128 process.exit(1);
129 }
130 };
131 this.shutdownCleanupRef = cleanup;
132 signals.forEach((signal) => {
133 this.activeShutdownSignals.push(signal);
134 process.on(signal, cleanup);
135 });
136 }
137 /**
138 * Unsubscribes from shutdown signals (process events)
139 */
140 unsubscribeFromProcessSignals() {
141 if (!this.shutdownCleanupRef) {
142 return;
143 }
144 this.activeShutdownSignals.forEach(signal => {
145 process.removeListener(signal, this.shutdownCleanupRef);
146 });
147 }
148 /**
149 * Calls the `onModuleInit` function on the registered
150 * modules and its children.
151 */
152 async callInitHook() {
153 const modulesContainer = this.container.getModules();
154 for (const module of [...modulesContainer.values()].reverse()) {
155 await hooks_1.callModuleInitHook(module);
156 }
157 }
158 /**
159 * Calls the `onModuleDestroy` function on the registered
160 * modules and its children.
161 */
162 async callDestroyHook() {
163 const modulesContainer = this.container.getModules();
164 for (const module of modulesContainer.values()) {
165 await hooks_1.callModuleDestroyHook(module);
166 }
167 }
168 /**
169 * Calls the `onApplicationBootstrap` function on the registered
170 * modules and its children.
171 */
172 async callBootstrapHook() {
173 const modulesContainer = this.container.getModules();
174 for (const module of [...modulesContainer.values()].reverse()) {
175 await hooks_1.callModuleBootstrapHook(module);
176 }
177 }
178 /**
179 * Calls the `onApplicationShutdown` function on the registered
180 * modules and children.
181 */
182 async callShutdownHook(signal) {
183 const modulesContainer = this.container.getModules();
184 for (const module of [...modulesContainer.values()].reverse()) {
185 await hooks_1.callAppShutdownHook(module, signal);
186 }
187 }
188 /**
189 * Calls the `beforeApplicationShutdown` function on the registered
190 * modules and children.
191 */
192 async callBeforeShutdownHook(signal) {
193 const modulesContainer = this.container.getModules();
194 for (const module of [...modulesContainer.values()].reverse()) {
195 await hooks_1.callBeforeAppShutdownHook(module, signal);
196 }
197 }
198 find(typeOrToken) {
199 return this.containerScanner.find(typeOrToken);
200 }
201 findInstanceByToken(metatypeOrToken, contextModule) {
202 return this.containerScanner.findInstanceByToken(metatypeOrToken, contextModule);
203 }
204 async resolvePerContext(typeOrToken, contextModule, contextId, options) {
205 let wrapper, collection;
206 if (!(options && options.strict)) {
207 [wrapper, collection] = this.containerScanner.getWrapperCollectionPair(typeOrToken);
208 }
209 else {
210 [
211 wrapper,
212 collection,
213 ] = this.containerScanner.getWrapperCollectionPairByHost(typeOrToken, contextModule);
214 }
215 const instance = await this.injector.loadPerContext(wrapper.instance, wrapper.host, collection, contextId);
216 if (!instance) {
217 throw new unknown_element_exception_1.UnknownElementException();
218 }
219 return instance;
220 }
221}
222exports.NestApplicationContext = NestApplicationContext;