1 | "use strict";
|
2 | var _a;
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | const tslib_1 = require("tslib");
|
5 | const common_1 = require("@nestjs/common");
|
6 | const random_string_generator_util_1 = require("@nestjs/common/utils/random-string-generator.util");
|
7 | const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
|
8 | const constants_1 = require("./constants");
|
9 | exports.INSTANCE_METADATA_SYMBOL = Symbol.for('instance_metadata:cache');
|
10 | exports.INSTANCE_ID_SYMBOL = Symbol.for('instance_metadata:id');
|
11 | class 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 | }
|
228 | exports.InstanceWrapper = InstanceWrapper;
|
229 | _a = exports.INSTANCE_METADATA_SYMBOL;
|