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