1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const random_string_generator_util_1 = require("@nestjs/common/utils/random-string-generator.util");
|
4 | const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
|
5 | const application_config_1 = require("../application-config");
|
6 | const invalid_class_exception_1 = require("../errors/exceptions/invalid-class.exception");
|
7 | const runtime_exception_1 = require("../errors/exceptions/runtime.exception");
|
8 | const unknown_export_exception_1 = require("../errors/exceptions/unknown-export.exception");
|
9 | const helpers_1 = require("../helpers");
|
10 | const get_class_scope_1 = require("../helpers/get-class-scope");
|
11 | const constants_1 = require("./constants");
|
12 | const instance_wrapper_1 = require("./instance-wrapper");
|
13 | const module_ref_1 = require("./module-ref");
|
14 | class 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 |
|
46 |
|
47 | get relatedModules() {
|
48 | return this._imports;
|
49 | }
|
50 | |
51 |
|
52 |
|
53 | get components() {
|
54 | return this._providers;
|
55 | }
|
56 | |
57 |
|
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 |
|
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 | }
|
355 | exports.Module = Module;
|