UNPKG

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