UNPKG

12 kBJavaScriptView Raw
1"use strict";
2var _a;
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.InstanceWrapper = exports.INSTANCE_ID_SYMBOL = exports.INSTANCE_METADATA_SYMBOL = void 0;
5const tslib_1 = require("tslib");
6const common_1 = require("@nestjs/common");
7const cli_colors_util_1 = require("@nestjs/common/utils/cli-colors.util");
8const random_string_generator_util_1 = require("@nestjs/common/utils/random-string-generator.util");
9const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
10const iterare_1 = require("iterare");
11const constants_1 = require("./constants");
12const provider_classifier_1 = require("./helpers/provider-classifier");
13exports.INSTANCE_METADATA_SYMBOL = Symbol.for('instance_metadata:cache');
14exports.INSTANCE_ID_SYMBOL = Symbol.for('instance_metadata:id');
15class 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}
275exports.InstanceWrapper = InstanceWrapper;
276_a = exports.INSTANCE_METADATA_SYMBOL;
277InstanceWrapper.logger = new common_1.Logger(InstanceWrapper.name);