UNPKG

13.1 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.Module = void 0;
4const random_string_generator_util_1 = require("@nestjs/common/utils/random-string-generator.util");
5const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
6const iterare_1 = require("iterare");
7const application_config_1 = require("../application-config");
8const invalid_class_exception_1 = require("../errors/exceptions/invalid-class.exception");
9const runtime_exception_1 = require("../errors/exceptions/runtime.exception");
10const unknown_export_exception_1 = require("../errors/exceptions/unknown-export.exception");
11const context_id_factory_1 = require("../helpers/context-id-factory");
12const get_class_scope_1 = require("../helpers/get-class-scope");
13const constants_1 = require("./constants");
14const instance_wrapper_1 = require("./instance-wrapper");
15const module_ref_1 = require("./module-ref");
16class Module {
17 constructor(_metatype, container) {
18 this._metatype = _metatype;
19 this.container = container;
20 this._imports = new Set();
21 this._providers = new Map();
22 this._injectables = new Map();
23 this._middlewares = new Map();
24 this._controllers = new Map();
25 this._exports = new Set();
26 this._distance = 0;
27 this.addCoreProviders();
28 this._id = random_string_generator_util_1.randomStringGenerator();
29 }
30 get id() {
31 return this._id;
32 }
33 get token() {
34 return this._token;
35 }
36 set token(token) {
37 this._token = token;
38 }
39 get providers() {
40 return this._providers;
41 }
42 get middlewares() {
43 return this._middlewares;
44 }
45 get imports() {
46 return this._imports;
47 }
48 /**
49 * Left for backward-compatibility reasons
50 */
51 get relatedModules() {
52 return this._imports;
53 }
54 /**
55 * Left for backward-compatibility reasons
56 */
57 get components() {
58 return this._providers;
59 }
60 /**
61 * Left for backward-compatibility reasons
62 */
63 get routes() {
64 return this._controllers;
65 }
66 get injectables() {
67 return this._injectables;
68 }
69 get controllers() {
70 return this._controllers;
71 }
72 get exports() {
73 return this._exports;
74 }
75 get instance() {
76 if (!this._providers.has(this._metatype)) {
77 throw new runtime_exception_1.RuntimeException();
78 }
79 const module = this._providers.get(this._metatype);
80 return module.instance;
81 }
82 get metatype() {
83 return this._metatype;
84 }
85 get distance() {
86 return this._distance;
87 }
88 set distance(value) {
89 this._distance = value;
90 }
91 addCoreProviders() {
92 this.addModuleAsProvider();
93 this.addModuleRef();
94 this.addApplicationConfig();
95 }
96 addModuleRef() {
97 const moduleRef = this.createModuleReferenceType();
98 this._providers.set(module_ref_1.ModuleRef, new instance_wrapper_1.InstanceWrapper({
99 token: module_ref_1.ModuleRef,
100 name: module_ref_1.ModuleRef.name,
101 metatype: module_ref_1.ModuleRef,
102 isResolved: true,
103 instance: new moduleRef(),
104 host: this,
105 }));
106 }
107 addModuleAsProvider() {
108 this._providers.set(this._metatype, new instance_wrapper_1.InstanceWrapper({
109 token: this._metatype,
110 name: this._metatype.name,
111 metatype: this._metatype,
112 isResolved: false,
113 instance: null,
114 host: this,
115 }));
116 }
117 addApplicationConfig() {
118 this._providers.set(application_config_1.ApplicationConfig, new instance_wrapper_1.InstanceWrapper({
119 token: application_config_1.ApplicationConfig,
120 name: application_config_1.ApplicationConfig.name,
121 isResolved: true,
122 instance: this.container.applicationConfig,
123 host: this,
124 }));
125 }
126 addInjectable(injectable, host) {
127 if (this.isCustomProvider(injectable)) {
128 return this.addCustomProvider(injectable, this._injectables);
129 }
130 let instanceWrapper = this.injectables.get(injectable);
131 if (!instanceWrapper) {
132 instanceWrapper = new instance_wrapper_1.InstanceWrapper({
133 token: injectable,
134 name: injectable.name,
135 metatype: injectable,
136 instance: null,
137 isResolved: false,
138 scope: get_class_scope_1.getClassScope(injectable),
139 host: this,
140 });
141 this._injectables.set(injectable, instanceWrapper);
142 }
143 if (host) {
144 const hostWrapper = this._controllers.get(host) || this._providers.get(host);
145 hostWrapper && hostWrapper.addEnhancerMetadata(instanceWrapper);
146 }
147 }
148 addProvider(provider) {
149 if (this.isCustomProvider(provider)) {
150 return this.addCustomProvider(provider, this._providers);
151 }
152 this._providers.set(provider, new instance_wrapper_1.InstanceWrapper({
153 token: provider,
154 name: provider.name,
155 metatype: provider,
156 instance: null,
157 isResolved: false,
158 scope: get_class_scope_1.getClassScope(provider),
159 host: this,
160 }));
161 return provider;
162 }
163 isCustomProvider(provider) {
164 return !shared_utils_1.isNil(provider.provide);
165 }
166 addCustomProvider(provider, collection) {
167 if (this.isCustomClass(provider)) {
168 this.addCustomClass(provider, collection);
169 }
170 else if (this.isCustomValue(provider)) {
171 this.addCustomValue(provider, collection);
172 }
173 else if (this.isCustomFactory(provider)) {
174 this.addCustomFactory(provider, collection);
175 }
176 else if (this.isCustomUseExisting(provider)) {
177 this.addCustomUseExisting(provider, collection);
178 }
179 return provider.provide;
180 }
181 isCustomClass(provider) {
182 return !shared_utils_1.isUndefined(provider.useClass);
183 }
184 isCustomValue(provider) {
185 return !shared_utils_1.isUndefined(provider.useValue);
186 }
187 isCustomFactory(provider) {
188 return !shared_utils_1.isUndefined(provider.useFactory);
189 }
190 isCustomUseExisting(provider) {
191 return !shared_utils_1.isUndefined(provider.useExisting);
192 }
193 isDynamicModule(exported) {
194 return exported && exported.module;
195 }
196 addCustomClass(provider, collection) {
197 let { scope } = provider;
198 const { useClass } = provider;
199 if (shared_utils_1.isUndefined(scope)) {
200 scope = get_class_scope_1.getClassScope(useClass);
201 }
202 collection.set(provider.provide, new instance_wrapper_1.InstanceWrapper({
203 token: provider.provide,
204 name: (useClass === null || useClass === void 0 ? void 0 : useClass.name) || useClass,
205 metatype: useClass,
206 instance: null,
207 isResolved: false,
208 scope,
209 host: this,
210 }));
211 }
212 addCustomValue(provider, collection) {
213 var _a;
214 const { useValue: value, provide: providerToken } = provider;
215 collection.set(providerToken, new instance_wrapper_1.InstanceWrapper({
216 token: providerToken,
217 name: ((_a = providerToken) === null || _a === void 0 ? void 0 : _a.name) || providerToken,
218 metatype: null,
219 instance: value,
220 isResolved: true,
221 async: value instanceof Promise,
222 host: this,
223 }));
224 }
225 addCustomFactory(provider, collection) {
226 var _a;
227 const { useFactory: factory, inject, scope, provide: providerToken, } = provider;
228 collection.set(providerToken, new instance_wrapper_1.InstanceWrapper({
229 token: providerToken,
230 name: ((_a = providerToken) === null || _a === void 0 ? void 0 : _a.name) || providerToken,
231 metatype: factory,
232 instance: null,
233 isResolved: false,
234 inject: inject || [],
235 scope,
236 host: this,
237 }));
238 }
239 addCustomUseExisting(provider, collection) {
240 var _a;
241 const { useExisting, provide: providerToken } = provider;
242 collection.set(providerToken, new instance_wrapper_1.InstanceWrapper({
243 token: providerToken,
244 name: ((_a = providerToken) === null || _a === void 0 ? void 0 : _a.name) || providerToken,
245 metatype: (instance => instance),
246 instance: null,
247 isResolved: false,
248 inject: [useExisting],
249 host: this,
250 isAlias: true,
251 }));
252 }
253 addExportedProvider(provider) {
254 const addExportedUnit = (token) => this._exports.add(this.validateExportedProvider(token));
255 if (this.isCustomProvider(provider)) {
256 return this.addCustomExportedProvider(provider);
257 }
258 else if (shared_utils_1.isString(provider) || shared_utils_1.isSymbol(provider)) {
259 return addExportedUnit(provider);
260 }
261 else if (this.isDynamicModule(provider)) {
262 const { module: moduleClassRef } = provider;
263 return addExportedUnit(moduleClassRef);
264 }
265 addExportedUnit(provider);
266 }
267 addCustomExportedProvider(provider) {
268 const provide = provider.provide;
269 if (shared_utils_1.isString(provide) || shared_utils_1.isSymbol(provide)) {
270 return this._exports.add(this.validateExportedProvider(provide));
271 }
272 this._exports.add(this.validateExportedProvider(provide));
273 }
274 validateExportedProvider(token) {
275 if (this._providers.has(token)) {
276 return token;
277 }
278 const imports = iterare_1.iterate(this._imports.values())
279 .filter(item => !!item)
280 .map(({ metatype }) => metatype)
281 .filter(metatype => !!metatype)
282 .toArray();
283 if (!imports.includes(token)) {
284 const { name } = this.metatype;
285 const providerName = shared_utils_1.isFunction(token) ? token.name : token;
286 throw new unknown_export_exception_1.UnknownExportException(providerName, name);
287 }
288 return token;
289 }
290 addController(controller) {
291 this._controllers.set(controller, new instance_wrapper_1.InstanceWrapper({
292 token: controller,
293 name: controller.name,
294 metatype: controller,
295 instance: null,
296 isResolved: false,
297 scope: get_class_scope_1.getClassScope(controller),
298 host: this,
299 }));
300 this.assignControllerUniqueId(controller);
301 }
302 assignControllerUniqueId(controller) {
303 Object.defineProperty(controller, constants_1.CONTROLLER_ID_KEY, {
304 enumerable: false,
305 writable: false,
306 configurable: true,
307 value: random_string_generator_util_1.randomStringGenerator(),
308 });
309 }
310 addRelatedModule(module) {
311 this._imports.add(module);
312 }
313 replace(toReplace, options) {
314 if (options.isProvider && this.hasProvider(toReplace)) {
315 const originalProvider = this._providers.get(toReplace);
316 return originalProvider.mergeWith(Object.assign({ provide: toReplace }, options));
317 }
318 else if (!options.isProvider && this.hasInjectable(toReplace)) {
319 const originalInjectable = this._injectables.get(toReplace);
320 return originalInjectable.mergeWith(Object.assign({ provide: toReplace }, options));
321 }
322 }
323 hasProvider(token) {
324 return this._providers.has(token);
325 }
326 hasInjectable(token) {
327 return this._injectables.has(token);
328 }
329 getProviderByKey(name) {
330 return this._providers.get(name);
331 }
332 getNonAliasProviders() {
333 return [...this._providers].filter(([_, wrapper]) => !wrapper.isAlias);
334 }
335 createModuleReferenceType() {
336 // eslint-disable-next-line @typescript-eslint/no-this-alias
337 const self = this;
338 return class extends module_ref_1.ModuleRef {
339 constructor() {
340 super(self.container);
341 }
342 get(typeOrToken, options = { strict: true }) {
343 return !(options && options.strict)
344 ? this.find(typeOrToken)
345 : this.find(typeOrToken, self);
346 }
347 resolve(typeOrToken, contextId = context_id_factory_1.createContextId(), options = { strict: true }) {
348 return this.resolvePerContext(typeOrToken, self, contextId, options);
349 }
350 async create(type) {
351 if (!(type && shared_utils_1.isFunction(type) && type.prototype)) {
352 throw new invalid_class_exception_1.InvalidClassException(type);
353 }
354 return this.instantiateClass(type, self);
355 }
356 };
357 }
358}
359exports.Module = Module;