UNPKG

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