1 | "use strict";
|
2 | var _a;
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.InstanceWrapper = exports.INSTANCE_ID_SYMBOL = exports.INSTANCE_METADATA_SYMBOL = void 0;
|
5 | const common_1 = require("@nestjs/common");
|
6 | const cli_colors_util_1 = require("@nestjs/common/utils/cli-colors.util");
|
7 | const random_string_generator_util_1 = require("@nestjs/common/utils/random-string-generator.util");
|
8 | const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
|
9 | const iterare_1 = require("iterare");
|
10 | const uuid_factory_1 = require("../inspector/uuid-factory");
|
11 | const constants_1 = require("./constants");
|
12 | const provider_classifier_1 = require("./helpers/provider-classifier");
|
13 | exports.INSTANCE_METADATA_SYMBOL = Symbol.for('instance_metadata:cache');
|
14 | exports.INSTANCE_ID_SYMBOL = Symbol.for('instance_metadata:id');
|
15 | class InstanceWrapper {
|
16 | constructor(metadata = {}) {
|
17 | this.isAlias = false;
|
18 | this.scope = common_1.Scope.DEFAULT;
|
19 | this.values = new WeakMap();
|
20 | this[_a] = {};
|
21 | this.initialize(metadata);
|
22 | this[exports.INSTANCE_ID_SYMBOL] =
|
23 | metadata[exports.INSTANCE_ID_SYMBOL] ?? this.generateUuid();
|
24 | }
|
25 | get id() {
|
26 | return this[exports.INSTANCE_ID_SYMBOL];
|
27 | }
|
28 | set instance(value) {
|
29 | this.values.set(constants_1.STATIC_CONTEXT, { instance: value });
|
30 | }
|
31 | get instance() {
|
32 | const instancePerContext = this.getInstanceByContextId(constants_1.STATIC_CONTEXT);
|
33 | return instancePerContext.instance;
|
34 | }
|
35 | get isNotMetatype() {
|
36 | return !this.metatype || this.isFactory;
|
37 | }
|
38 | get isFactory() {
|
39 | return this.metatype && !(0, shared_utils_1.isNil)(this.inject);
|
40 | }
|
41 | get isTransient() {
|
42 | return this.scope === common_1.Scope.TRANSIENT;
|
43 | }
|
44 | getInstanceByContextId(contextId, inquirerId) {
|
45 | if (this.scope === common_1.Scope.TRANSIENT && inquirerId) {
|
46 | return this.getInstanceByInquirerId(contextId, inquirerId);
|
47 | }
|
48 | const instancePerContext = this.values.get(contextId);
|
49 | return instancePerContext
|
50 | ? instancePerContext
|
51 | : this.cloneStaticInstance(contextId);
|
52 | }
|
53 | getInstanceByInquirerId(contextId, inquirerId) {
|
54 | let collectionPerContext = this.transientMap.get(inquirerId);
|
55 | if (!collectionPerContext) {
|
56 | collectionPerContext = new WeakMap();
|
57 | this.transientMap.set(inquirerId, collectionPerContext);
|
58 | }
|
59 | const instancePerContext = collectionPerContext.get(contextId);
|
60 | return instancePerContext
|
61 | ? instancePerContext
|
62 | : this.cloneTransientInstance(contextId, inquirerId);
|
63 | }
|
64 | setInstanceByContextId(contextId, value, inquirerId) {
|
65 | if (this.scope === common_1.Scope.TRANSIENT && inquirerId) {
|
66 | return this.setInstanceByInquirerId(contextId, inquirerId, value);
|
67 | }
|
68 | this.values.set(contextId, value);
|
69 | }
|
70 | setInstanceByInquirerId(contextId, inquirerId, value) {
|
71 | let collection = this.transientMap.get(inquirerId);
|
72 | if (!collection) {
|
73 | collection = new WeakMap();
|
74 | this.transientMap.set(inquirerId, collection);
|
75 | }
|
76 | collection.set(contextId, value);
|
77 | }
|
78 | addCtorMetadata(index, wrapper) {
|
79 | if (!this[exports.INSTANCE_METADATA_SYMBOL].dependencies) {
|
80 | this[exports.INSTANCE_METADATA_SYMBOL].dependencies = [];
|
81 | }
|
82 | this[exports.INSTANCE_METADATA_SYMBOL].dependencies[index] = wrapper;
|
83 | }
|
84 | getCtorMetadata() {
|
85 | return this[exports.INSTANCE_METADATA_SYMBOL].dependencies;
|
86 | }
|
87 | addPropertiesMetadata(key, wrapper) {
|
88 | if (!this[exports.INSTANCE_METADATA_SYMBOL].properties) {
|
89 | this[exports.INSTANCE_METADATA_SYMBOL].properties = [];
|
90 | }
|
91 | this[exports.INSTANCE_METADATA_SYMBOL].properties.push({
|
92 | key,
|
93 | wrapper,
|
94 | });
|
95 | }
|
96 | getPropertiesMetadata() {
|
97 | return this[exports.INSTANCE_METADATA_SYMBOL].properties;
|
98 | }
|
99 | addEnhancerMetadata(wrapper) {
|
100 | if (!this[exports.INSTANCE_METADATA_SYMBOL].enhancers) {
|
101 | this[exports.INSTANCE_METADATA_SYMBOL].enhancers = [];
|
102 | }
|
103 | this[exports.INSTANCE_METADATA_SYMBOL].enhancers.push(wrapper);
|
104 | }
|
105 | getEnhancersMetadata() {
|
106 | return this[exports.INSTANCE_METADATA_SYMBOL].enhancers;
|
107 | }
|
108 | isDependencyTreeDurable(lookupRegistry = []) {
|
109 | if (!(0, shared_utils_1.isUndefined)(this.isTreeDurable)) {
|
110 | return this.isTreeDurable;
|
111 | }
|
112 | if (this.scope === common_1.Scope.REQUEST) {
|
113 | this.isTreeDurable = this.durable === undefined ? false : this.durable;
|
114 | if (this.isTreeDurable) {
|
115 | this.printIntrospectedAsDurable();
|
116 | }
|
117 | return this.isTreeDurable;
|
118 | }
|
119 | const isStatic = this.isDependencyTreeStatic();
|
120 | if (isStatic) {
|
121 | return false;
|
122 | }
|
123 | const isTreeNonDurable = this.introspectDepsAttribute((collection, registry) => collection.some((item) => !item.isDependencyTreeStatic() &&
|
124 | !item.isDependencyTreeDurable(registry)), lookupRegistry);
|
125 | this.isTreeDurable = !isTreeNonDurable;
|
126 | if (this.isTreeDurable) {
|
127 | this.printIntrospectedAsDurable();
|
128 | }
|
129 | return this.isTreeDurable;
|
130 | }
|
131 | introspectDepsAttribute(callback, lookupRegistry = []) {
|
132 | if (lookupRegistry.includes(this[exports.INSTANCE_ID_SYMBOL])) {
|
133 | return false;
|
134 | }
|
135 | lookupRegistry = lookupRegistry.concat(this[exports.INSTANCE_ID_SYMBOL]);
|
136 | const { dependencies, properties, enhancers } = this[exports.INSTANCE_METADATA_SYMBOL];
|
137 | let introspectionResult = dependencies
|
138 | ? callback(dependencies, lookupRegistry)
|
139 | : false;
|
140 | if (introspectionResult || !(properties || enhancers)) {
|
141 | return introspectionResult;
|
142 | }
|
143 | introspectionResult = properties
|
144 | ? callback(properties.map(item => item.wrapper), lookupRegistry)
|
145 | : false;
|
146 | if (introspectionResult || !enhancers) {
|
147 | return introspectionResult;
|
148 | }
|
149 | return enhancers ? callback(enhancers, lookupRegistry) : false;
|
150 | }
|
151 | isDependencyTreeStatic(lookupRegistry = []) {
|
152 | if (!(0, shared_utils_1.isUndefined)(this.isTreeStatic)) {
|
153 | return this.isTreeStatic;
|
154 | }
|
155 | if (this.scope === common_1.Scope.REQUEST) {
|
156 | this.isTreeStatic = false;
|
157 | this.printIntrospectedAsRequestScoped();
|
158 | return this.isTreeStatic;
|
159 | }
|
160 | this.isTreeStatic = !this.introspectDepsAttribute((collection, registry) => collection.some((item) => !item.isDependencyTreeStatic(registry)), lookupRegistry);
|
161 | if (!this.isTreeStatic) {
|
162 | this.printIntrospectedAsRequestScoped();
|
163 | }
|
164 | return this.isTreeStatic;
|
165 | }
|
166 | cloneStaticInstance(contextId) {
|
167 | const staticInstance = this.getInstanceByContextId(constants_1.STATIC_CONTEXT);
|
168 | if (this.isDependencyTreeStatic()) {
|
169 | return staticInstance;
|
170 | }
|
171 | const instancePerContext = {
|
172 | ...staticInstance,
|
173 | instance: undefined,
|
174 | isResolved: false,
|
175 | isPending: false,
|
176 | };
|
177 | if (this.isNewable()) {
|
178 | instancePerContext.instance = Object.create(this.metatype.prototype);
|
179 | }
|
180 | this.setInstanceByContextId(contextId, instancePerContext);
|
181 | return instancePerContext;
|
182 | }
|
183 | cloneTransientInstance(contextId, inquirerId) {
|
184 | const staticInstance = this.getInstanceByContextId(constants_1.STATIC_CONTEXT);
|
185 | const instancePerContext = {
|
186 | ...staticInstance,
|
187 | instance: undefined,
|
188 | isResolved: false,
|
189 | isPending: false,
|
190 | };
|
191 | if (this.isNewable()) {
|
192 | instancePerContext.instance = Object.create(this.metatype.prototype);
|
193 | }
|
194 | this.setInstanceByInquirerId(contextId, inquirerId, instancePerContext);
|
195 | return instancePerContext;
|
196 | }
|
197 | createPrototype(contextId) {
|
198 | const host = this.getInstanceByContextId(contextId);
|
199 | if (!this.isNewable() || host.isResolved) {
|
200 | return;
|
201 | }
|
202 | return Object.create(this.metatype.prototype);
|
203 | }
|
204 | isInRequestScope(contextId, inquirer) {
|
205 | const isDependencyTreeStatic = this.isDependencyTreeStatic();
|
206 | return (!isDependencyTreeStatic &&
|
207 | contextId !== constants_1.STATIC_CONTEXT &&
|
208 | (!this.isTransient || (this.isTransient && !!inquirer)));
|
209 | }
|
210 | isLazyTransient(contextId, inquirer) {
|
211 | const isInquirerRequestScoped = inquirer && !inquirer.isDependencyTreeStatic();
|
212 | return (this.isDependencyTreeStatic() &&
|
213 | contextId !== constants_1.STATIC_CONTEXT &&
|
214 | this.isTransient &&
|
215 | isInquirerRequestScoped);
|
216 | }
|
217 | isExplicitlyRequested(contextId, inquirer) {
|
218 | const isSelfRequested = inquirer === this;
|
219 | return (this.isDependencyTreeStatic() &&
|
220 | contextId !== constants_1.STATIC_CONTEXT &&
|
221 | (isSelfRequested || (inquirer && inquirer.scope === common_1.Scope.TRANSIENT)));
|
222 | }
|
223 | isStatic(contextId, inquirer) {
|
224 | const isInquirerRequestScoped = inquirer && !inquirer.isDependencyTreeStatic();
|
225 | const isStaticTransient = this.isTransient && !isInquirerRequestScoped;
|
226 | return (this.isDependencyTreeStatic() &&
|
227 | contextId === constants_1.STATIC_CONTEXT &&
|
228 | (!this.isTransient ||
|
229 | (isStaticTransient && !!inquirer && !inquirer.isTransient)));
|
230 | }
|
231 | getStaticTransientInstances() {
|
232 | if (!this.transientMap) {
|
233 | return [];
|
234 | }
|
235 | const instances = [...this.transientMap.values()];
|
236 | return (0, iterare_1.iterate)(instances)
|
237 | .map(item => item.get(constants_1.STATIC_CONTEXT))
|
238 | .filter(item => !!item)
|
239 | .toArray();
|
240 | }
|
241 | mergeWith(provider) {
|
242 | if ((0, provider_classifier_1.isValueProvider)(provider)) {
|
243 | this.metatype = null;
|
244 | this.inject = null;
|
245 | this.scope = common_1.Scope.DEFAULT;
|
246 | this.setInstanceByContextId(constants_1.STATIC_CONTEXT, {
|
247 | instance: provider.useValue,
|
248 | isResolved: true,
|
249 | isPending: false,
|
250 | });
|
251 | }
|
252 | else if ((0, provider_classifier_1.isClassProvider)(provider)) {
|
253 | this.inject = null;
|
254 | this.metatype = provider.useClass;
|
255 | }
|
256 | else if ((0, provider_classifier_1.isFactoryProvider)(provider)) {
|
257 | this.metatype = provider.useFactory;
|
258 | this.inject = provider.inject || [];
|
259 | }
|
260 | }
|
261 | isNewable() {
|
262 | return (0, shared_utils_1.isNil)(this.inject) && this.metatype && this.metatype.prototype;
|
263 | }
|
264 | initialize(metadata) {
|
265 | const { instance, isResolved, ...wrapperPartial } = metadata;
|
266 | Object.assign(this, wrapperPartial);
|
267 | this.setInstanceByContextId(constants_1.STATIC_CONTEXT, {
|
268 | instance,
|
269 | isResolved,
|
270 | });
|
271 | this.scope === common_1.Scope.TRANSIENT && (this.transientMap = new Map());
|
272 | }
|
273 | printIntrospectedAsRequestScoped() {
|
274 | if (!this.isDebugMode() || this.name === 'REQUEST') {
|
275 | return;
|
276 | }
|
277 | if ((0, shared_utils_1.isString)(this.name)) {
|
278 | InstanceWrapper.logger.log(`${cli_colors_util_1.clc.cyanBright(this.name)}${cli_colors_util_1.clc.green(' introspected as ')}${cli_colors_util_1.clc.magentaBright('request-scoped')}`);
|
279 | }
|
280 | }
|
281 | printIntrospectedAsDurable() {
|
282 | if (!this.isDebugMode()) {
|
283 | return;
|
284 | }
|
285 | if ((0, shared_utils_1.isString)(this.name)) {
|
286 | InstanceWrapper.logger.log(`${cli_colors_util_1.clc.cyanBright(this.name)}${cli_colors_util_1.clc.green(' introspected as ')}${cli_colors_util_1.clc.magentaBright('durable')}`);
|
287 | }
|
288 | }
|
289 | isDebugMode() {
|
290 | return !!process.env.NEST_DEBUG;
|
291 | }
|
292 | generateUuid() {
|
293 | let key = this.name?.toString() ?? this.token?.toString();
|
294 | key += this.host?.name ?? '';
|
295 | return key ? uuid_factory_1.UuidFactory.get(key) : (0, random_string_generator_util_1.randomStringGenerator)();
|
296 | }
|
297 | }
|
298 | exports.InstanceWrapper = InstanceWrapper;
|
299 | _a = exports.INSTANCE_METADATA_SYMBOL;
|
300 | InstanceWrapper.logger = new common_1.Logger(InstanceWrapper.name);
|