UNPKG

9.52 kBJavaScriptView Raw
1"use strict";
2var _a;
3Object.defineProperty(exports, "__esModule", { value: true });
4const tslib_1 = require("tslib");
5const common_1 = require("@nestjs/common");
6const random_string_generator_util_1 = require("@nestjs/common/utils/random-string-generator.util");
7const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
8const constants_1 = require("./constants");
9exports.INSTANCE_METADATA_SYMBOL = Symbol.for('instance_metadata:cache');
10exports.INSTANCE_ID_SYMBOL = Symbol.for('instance_metadata:id');
11class InstanceWrapper {
12 constructor(metadata = {}) {
13 this.scope = common_1.Scope.DEFAULT;
14 this.isAlias = false;
15 this.values = new WeakMap();
16 this[_a] = {};
17 this[exports.INSTANCE_ID_SYMBOL] = random_string_generator_util_1.randomStringGenerator();
18 this.initialize(metadata);
19 }
20 get id() {
21 return this[exports.INSTANCE_ID_SYMBOL];
22 }
23 set instance(value) {
24 this.values.set(constants_1.STATIC_CONTEXT, { instance: value });
25 }
26 get instance() {
27 const instancePerContext = this.getInstanceByContextId(constants_1.STATIC_CONTEXT);
28 return instancePerContext.instance;
29 }
30 get isNotMetatype() {
31 const isFactory = this.metatype && !shared_utils_1.isNil(this.inject);
32 return !this.metatype || isFactory;
33 }
34 get isTransient() {
35 return this.scope === common_1.Scope.TRANSIENT;
36 }
37 getInstanceByContextId(contextId, inquirerId) {
38 if (this.scope === common_1.Scope.TRANSIENT && inquirerId) {
39 return this.getInstanceByInquirerId(contextId, inquirerId);
40 }
41 const instancePerContext = this.values.get(contextId);
42 return instancePerContext
43 ? instancePerContext
44 : this.cloneStaticInstance(contextId);
45 }
46 getInstanceByInquirerId(contextId, inquirerId) {
47 let collectionPerContext = this.transientMap.get(inquirerId);
48 if (!collectionPerContext) {
49 collectionPerContext = new WeakMap();
50 this.transientMap.set(inquirerId, collectionPerContext);
51 }
52 const instancePerContext = collectionPerContext.get(contextId);
53 return instancePerContext
54 ? instancePerContext
55 : this.cloneTransientInstance(contextId, inquirerId);
56 }
57 setInstanceByContextId(contextId, value, inquirerId) {
58 if (this.scope === common_1.Scope.TRANSIENT && inquirerId) {
59 return this.setInstanceByInquirerId(contextId, inquirerId, value);
60 }
61 this.values.set(contextId, value);
62 }
63 setInstanceByInquirerId(contextId, inquirerId, value) {
64 let collection = this.transientMap.get(inquirerId);
65 if (!collection) {
66 collection = new WeakMap();
67 this.transientMap.set(inquirerId, collection);
68 }
69 collection.set(contextId, value);
70 }
71 addCtorMetadata(index, wrapper) {
72 if (!this[exports.INSTANCE_METADATA_SYMBOL].dependencies) {
73 this[exports.INSTANCE_METADATA_SYMBOL].dependencies = [];
74 }
75 this[exports.INSTANCE_METADATA_SYMBOL].dependencies[index] = wrapper;
76 }
77 getCtorMetadata() {
78 return this[exports.INSTANCE_METADATA_SYMBOL].dependencies;
79 }
80 addPropertiesMetadata(key, wrapper) {
81 if (!this[exports.INSTANCE_METADATA_SYMBOL].properties) {
82 this[exports.INSTANCE_METADATA_SYMBOL].properties = [];
83 }
84 this[exports.INSTANCE_METADATA_SYMBOL].properties.push({
85 key,
86 wrapper,
87 });
88 }
89 getPropertiesMetadata() {
90 return this[exports.INSTANCE_METADATA_SYMBOL].properties;
91 }
92 addEnhancerMetadata(wrapper) {
93 if (!this[exports.INSTANCE_METADATA_SYMBOL].enhancers) {
94 this[exports.INSTANCE_METADATA_SYMBOL].enhancers = [];
95 }
96 this[exports.INSTANCE_METADATA_SYMBOL].enhancers.push(wrapper);
97 }
98 getEnhancersMetadata() {
99 return this[exports.INSTANCE_METADATA_SYMBOL].enhancers;
100 }
101 isDependencyTreeStatic(lookupRegistry = []) {
102 if (!shared_utils_1.isUndefined(this.isTreeStatic)) {
103 return this.isTreeStatic;
104 }
105 if (this.scope === common_1.Scope.REQUEST) {
106 this.isTreeStatic = false;
107 return this.isTreeStatic;
108 }
109 if (lookupRegistry.includes(this[exports.INSTANCE_ID_SYMBOL])) {
110 return true;
111 }
112 lookupRegistry = lookupRegistry.concat(this[exports.INSTANCE_ID_SYMBOL]);
113 const { dependencies, properties, enhancers } = this[exports.INSTANCE_METADATA_SYMBOL];
114 let isStatic = (dependencies &&
115 this.isWrapperListStatic(dependencies, lookupRegistry)) ||
116 !dependencies;
117 if (!isStatic || !(properties || enhancers)) {
118 this.isTreeStatic = isStatic;
119 return this.isTreeStatic;
120 }
121 const propertiesHosts = (properties || []).map(item => item.wrapper);
122 isStatic =
123 isStatic && this.isWrapperListStatic(propertiesHosts, lookupRegistry);
124 if (!isStatic || !enhancers) {
125 this.isTreeStatic = isStatic;
126 return this.isTreeStatic;
127 }
128 this.isTreeStatic = this.isWrapperListStatic(enhancers, lookupRegistry);
129 return this.isTreeStatic;
130 }
131 cloneStaticInstance(contextId) {
132 const staticInstance = this.getInstanceByContextId(constants_1.STATIC_CONTEXT);
133 if (this.isDependencyTreeStatic()) {
134 return staticInstance;
135 }
136 const instancePerContext = Object.assign(Object.assign({}, staticInstance), { instance: undefined, isResolved: false, isPending: false });
137 if (this.isNewable()) {
138 instancePerContext.instance = Object.create(this.metatype.prototype);
139 }
140 this.setInstanceByContextId(contextId, instancePerContext);
141 return instancePerContext;
142 }
143 cloneTransientInstance(contextId, inquirerId) {
144 const staticInstance = this.getInstanceByContextId(constants_1.STATIC_CONTEXT);
145 const instancePerContext = Object.assign(Object.assign({}, staticInstance), { instance: undefined, isResolved: false, isPending: false });
146 if (this.isNewable()) {
147 instancePerContext.instance = Object.create(this.metatype.prototype);
148 }
149 this.setInstanceByInquirerId(contextId, inquirerId, instancePerContext);
150 return instancePerContext;
151 }
152 createPrototype(contextId) {
153 const host = this.getInstanceByContextId(contextId);
154 if (!this.isNewable() || host.isResolved) {
155 return;
156 }
157 return Object.create(this.metatype.prototype);
158 }
159 isInRequestScope(contextId, inquirer) {
160 const isDependencyTreeStatic = this.isDependencyTreeStatic();
161 return (!isDependencyTreeStatic &&
162 contextId !== constants_1.STATIC_CONTEXT &&
163 (!this.isTransient || (this.isTransient && inquirer)));
164 }
165 isLazyTransient(contextId, inquirer) {
166 const isInquirerRequestScoped = inquirer && !inquirer.isDependencyTreeStatic();
167 return (this.isDependencyTreeStatic() &&
168 contextId !== constants_1.STATIC_CONTEXT &&
169 this.isTransient &&
170 isInquirerRequestScoped);
171 }
172 isExplicitlyRequested(contextId, inquirer) {
173 return (this.isDependencyTreeStatic() &&
174 contextId !== constants_1.STATIC_CONTEXT &&
175 inquirer === this);
176 }
177 isStatic(contextId, inquirer) {
178 const isInquirerRequestScoped = inquirer && !inquirer.isDependencyTreeStatic();
179 const isStaticTransient = this.isTransient && !isInquirerRequestScoped;
180 return (this.isDependencyTreeStatic() &&
181 contextId === constants_1.STATIC_CONTEXT &&
182 (!this.isTransient || (isStaticTransient && !!inquirer)));
183 }
184 getStaticTransientInstances() {
185 if (!this.transientMap) {
186 return [];
187 }
188 const instances = [...this.transientMap.values()];
189 return instances
190 .map(item => item.get(constants_1.STATIC_CONTEXT))
191 .filter(item => !!item);
192 }
193 mergeWith(provider) {
194 if (provider.useValue) {
195 this.metatype = null;
196 this.inject = null;
197 this.setInstanceByContextId(constants_1.STATIC_CONTEXT, {
198 instance: provider.useValue,
199 isResolved: true,
200 isPending: false,
201 });
202 }
203 else if (provider.useClass) {
204 this.inject = null;
205 this.metatype = provider.useClass;
206 }
207 else if (provider.useFactory) {
208 this.metatype = provider.useFactory;
209 this.inject = provider.inject || [];
210 }
211 }
212 isNewable() {
213 return shared_utils_1.isNil(this.inject) && this.metatype && this.metatype.prototype;
214 }
215 isWrapperListStatic(tree, lookupRegistry) {
216 return tree.every((item) => item.isDependencyTreeStatic(lookupRegistry));
217 }
218 initialize(metadata) {
219 const { instance, isResolved } = metadata, wrapperPartial = tslib_1.__rest(metadata, ["instance", "isResolved"]);
220 Object.assign(this, wrapperPartial);
221 this.setInstanceByContextId(constants_1.STATIC_CONTEXT, {
222 instance,
223 isResolved,
224 });
225 this.scope === common_1.Scope.TRANSIENT && (this.transientMap = new Map());
226 }
227}
228exports.InstanceWrapper = InstanceWrapper;
229_a = exports.INSTANCE_METADATA_SYMBOL;