UNPKG

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