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 random_string_generator_util_1 = require("@nestjs/common/utils/random-string-generator.util");
|
8 | const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
|
9 | const iterare_1 = require("iterare");
|
10 | const constants_1 = require("./constants");
|
11 | exports.INSTANCE_METADATA_SYMBOL = Symbol.for('instance_metadata:cache');
|
12 | exports.INSTANCE_ID_SYMBOL = Symbol.for('instance_metadata:id');
|
13 | class 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 | }
|
234 | exports.InstanceWrapper = InstanceWrapper;
|
235 | _a = exports.INSTANCE_METADATA_SYMBOL;
|