@navios/di 0.1.9 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/_tsup-dts-rollup.d.mts +558 -0
- package/lib/_tsup-dts-rollup.d.ts +558 -0
- package/lib/index.d.mts +61 -435
- package/lib/index.d.ts +61 -435
- package/lib/index.js +952 -720
- package/lib/index.js.map +1 -0
- package/lib/index.mjs +900 -670
- package/lib/index.mjs.map +1 -1
- package/package.json +5 -5
- package/project.json +4 -1
- package/src/__tests__/injectable.spec.mts +46 -2
- package/src/__tests__/service-locator.spec.mts +35 -0
- package/src/decorators/injectable.decorator.mts +24 -16
- package/src/injection-token.mts +0 -2
- package/src/injector.mts +2 -1
- package/src/resolve-service.mts +2 -2
- package/src/service-locator.mts +29 -18
- package/src/utils/get-injectors.mts +10 -2
- package/tsconfig.json +1 -1
- package/{tsdown.config.mts → tsup.config.mts} +4 -3
- package/lib/index.d.mts.map +0 -1
- package/lib/index.d.ts.map +0 -1
package/lib/index.js
CHANGED
|
@@ -1,795 +1,1027 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
//#region rolldown:runtime
|
|
3
|
-
var __create = Object.create;
|
|
4
2
|
var __defProp = Object.defineProperty;
|
|
5
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
9
10
|
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
18
17
|
};
|
|
19
|
-
var
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.mts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
BoundInjectionToken: () => BoundInjectionToken,
|
|
24
|
+
ErrorsEnum: () => ErrorsEnum,
|
|
25
|
+
EventEmitter: () => EventEmitter,
|
|
26
|
+
FactoryInjectionToken: () => FactoryInjectionToken,
|
|
27
|
+
FactoryNotFound: () => FactoryNotFound,
|
|
28
|
+
FactoryTokenNotResolved: () => FactoryTokenNotResolved,
|
|
29
|
+
Injectable: () => Injectable,
|
|
30
|
+
InjectableScope: () => InjectableScope,
|
|
31
|
+
InjectableTokenMeta: () => InjectableTokenMeta,
|
|
32
|
+
InjectableType: () => InjectableType,
|
|
33
|
+
InjectionToken: () => InjectionToken,
|
|
34
|
+
InjectorsBase: () => InjectorsBase,
|
|
35
|
+
InstanceDestroying: () => InstanceDestroying,
|
|
36
|
+
InstanceExpired: () => InstanceExpired,
|
|
37
|
+
InstanceNotFound: () => InstanceNotFound,
|
|
38
|
+
ProxyServiceLocator: () => ProxyServiceLocator,
|
|
39
|
+
Registry: () => Registry,
|
|
40
|
+
ServiceLocator: () => ServiceLocator,
|
|
41
|
+
ServiceLocatorEventBus: () => ServiceLocatorEventBus,
|
|
42
|
+
ServiceLocatorInstanceHolderKind: () => ServiceLocatorInstanceHolderKind,
|
|
43
|
+
ServiceLocatorInstanceHolderStatus: () => ServiceLocatorInstanceHolderStatus,
|
|
44
|
+
ServiceLocatorManager: () => ServiceLocatorManager,
|
|
45
|
+
UnknownError: () => UnknownError,
|
|
46
|
+
getGlobalServiceLocator: () => getGlobalServiceLocator,
|
|
47
|
+
getInjectableToken: () => getInjectableToken,
|
|
48
|
+
getInjectors: () => getInjectors,
|
|
49
|
+
globalRegistry: () => globalRegistry,
|
|
50
|
+
inject: () => inject,
|
|
51
|
+
makeProxyServiceLocator: () => makeProxyServiceLocator,
|
|
52
|
+
provideServiceLocator: () => provideServiceLocator,
|
|
53
|
+
resolveService: () => resolveService,
|
|
54
|
+
syncInject: () => syncInject,
|
|
55
|
+
wrapSyncInit: () => wrapSyncInit
|
|
56
|
+
});
|
|
57
|
+
module.exports = __toCommonJS(index_exports);
|
|
23
58
|
|
|
24
|
-
|
|
25
|
-
require("zod");
|
|
59
|
+
// src/decorators/injectable.decorator.mts
|
|
60
|
+
var import_zod3 = require("zod");
|
|
26
61
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Instance scope: A new instance is created for each injection.
|
|
35
|
-
*/
|
|
36
|
-
InjectableScope$1["Instance"] = "Instance";
|
|
37
|
-
return InjectableScope$1;
|
|
38
|
-
}({});
|
|
62
|
+
// src/enums/injectable-scope.enum.mts
|
|
63
|
+
var InjectableScope = /* @__PURE__ */ ((InjectableScope3) => {
|
|
64
|
+
InjectableScope3["Singleton"] = "Singleton";
|
|
65
|
+
InjectableScope3["Instance"] = "Instance";
|
|
66
|
+
return InjectableScope3;
|
|
67
|
+
})(InjectableScope || {});
|
|
39
68
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}({});
|
|
69
|
+
// src/enums/injectable-type.enum.mts
|
|
70
|
+
var InjectableType = /* @__PURE__ */ ((InjectableType2) => {
|
|
71
|
+
InjectableType2["Class"] = "Class";
|
|
72
|
+
InjectableType2["Factory"] = "Factory";
|
|
73
|
+
return InjectableType2;
|
|
74
|
+
})(InjectableType || {});
|
|
47
75
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
// src/injection-token.mts
|
|
77
|
+
var import_zod = require("zod");
|
|
78
|
+
var InjectionToken = class _InjectionToken {
|
|
79
|
+
constructor(name, schema) {
|
|
80
|
+
this.name = name;
|
|
81
|
+
this.schema = schema;
|
|
82
|
+
}
|
|
83
|
+
id = globalThis.crypto.randomUUID();
|
|
84
|
+
formattedName = null;
|
|
85
|
+
static create(name, schema) {
|
|
86
|
+
return new _InjectionToken(name, schema);
|
|
87
|
+
}
|
|
88
|
+
static bound(token, value) {
|
|
89
|
+
return new BoundInjectionToken(token, value);
|
|
90
|
+
}
|
|
91
|
+
static factory(token, factory) {
|
|
92
|
+
return new FactoryInjectionToken(token, factory);
|
|
93
|
+
}
|
|
94
|
+
static refineType(token) {
|
|
95
|
+
return token;
|
|
96
|
+
}
|
|
97
|
+
toString() {
|
|
98
|
+
if (this.formattedName) {
|
|
99
|
+
return this.formattedName;
|
|
100
|
+
}
|
|
101
|
+
const { name } = this;
|
|
102
|
+
if (typeof name === "function") {
|
|
103
|
+
const className = name.name;
|
|
104
|
+
this.formattedName = `${className}(${this.id})`;
|
|
105
|
+
} else if (typeof name === "symbol") {
|
|
106
|
+
this.formattedName = `${name.toString()}(${this.id})`;
|
|
107
|
+
} else {
|
|
108
|
+
this.formattedName = `${name}(${this.id})`;
|
|
109
|
+
}
|
|
110
|
+
return this.formattedName;
|
|
111
|
+
}
|
|
81
112
|
};
|
|
82
113
|
var BoundInjectionToken = class {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
114
|
+
constructor(token, value) {
|
|
115
|
+
this.token = token;
|
|
116
|
+
this.value = value;
|
|
117
|
+
this.name = token.name;
|
|
118
|
+
this.id = token.id;
|
|
119
|
+
this.schema = token.schema;
|
|
120
|
+
}
|
|
121
|
+
id;
|
|
122
|
+
name;
|
|
123
|
+
schema;
|
|
124
|
+
toString() {
|
|
125
|
+
return this.token.toString();
|
|
126
|
+
}
|
|
96
127
|
};
|
|
97
128
|
var FactoryInjectionToken = class {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
129
|
+
constructor(token, factory) {
|
|
130
|
+
this.token = token;
|
|
131
|
+
this.factory = factory;
|
|
132
|
+
this.name = token.name;
|
|
133
|
+
this.id = token.id;
|
|
134
|
+
this.schema = token.schema;
|
|
135
|
+
}
|
|
136
|
+
value;
|
|
137
|
+
resolved = false;
|
|
138
|
+
id;
|
|
139
|
+
name;
|
|
140
|
+
schema;
|
|
141
|
+
async resolve() {
|
|
142
|
+
if (!this.value) {
|
|
143
|
+
this.value = await this.factory();
|
|
144
|
+
this.resolved = true;
|
|
145
|
+
}
|
|
146
|
+
return this.value;
|
|
147
|
+
}
|
|
148
|
+
toString() {
|
|
149
|
+
return this.token.toString();
|
|
150
|
+
}
|
|
120
151
|
};
|
|
121
152
|
|
|
122
|
-
|
|
123
|
-
|
|
153
|
+
// src/registry.mts
|
|
154
|
+
var import_zod2 = require("zod");
|
|
124
155
|
var Registry = class {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
156
|
+
constructor(parent) {
|
|
157
|
+
this.parent = parent;
|
|
158
|
+
}
|
|
159
|
+
factories = /* @__PURE__ */ new Map();
|
|
160
|
+
has(token) {
|
|
161
|
+
if (this.factories.has(token.id)) {
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
if (this.parent) {
|
|
165
|
+
return this.parent.has(token);
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
get(token) {
|
|
170
|
+
const factory = this.factories.get(token.id);
|
|
171
|
+
if (!factory) {
|
|
172
|
+
if (this.parent) {
|
|
173
|
+
return this.parent.get(token);
|
|
174
|
+
}
|
|
175
|
+
throw new Error(`[Registry] No factory found for ${token.toString()}`);
|
|
176
|
+
}
|
|
177
|
+
return factory;
|
|
178
|
+
}
|
|
179
|
+
set(token, factory, scope) {
|
|
180
|
+
this.factories.set(token.id, { factory, scope, originalToken: token });
|
|
181
|
+
}
|
|
182
|
+
delete(token) {
|
|
183
|
+
this.factories.delete(token.id);
|
|
184
|
+
}
|
|
152
185
|
};
|
|
153
|
-
|
|
186
|
+
var globalRegistry = new Registry();
|
|
154
187
|
|
|
155
|
-
|
|
156
|
-
//#region src/proxy-service-locator.mts
|
|
188
|
+
// src/proxy-service-locator.mts
|
|
157
189
|
var ProxyServiceLocator = class {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
190
|
+
constructor(serviceLocator, ctx) {
|
|
191
|
+
this.serviceLocator = serviceLocator;
|
|
192
|
+
this.ctx = ctx;
|
|
193
|
+
}
|
|
194
|
+
getEventBus() {
|
|
195
|
+
return this.serviceLocator.getEventBus();
|
|
196
|
+
}
|
|
197
|
+
// @ts-expect-error We don't need all the properties of the class
|
|
198
|
+
getInstance(token, args) {
|
|
199
|
+
return this.ctx.inject(token, args).then(
|
|
200
|
+
(instance) => {
|
|
201
|
+
return [void 0, instance];
|
|
202
|
+
},
|
|
203
|
+
(error) => {
|
|
204
|
+
return [error];
|
|
205
|
+
}
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
getOrThrowInstance(token, args) {
|
|
209
|
+
return this.ctx.inject(token, args);
|
|
210
|
+
}
|
|
211
|
+
getSyncInstance(token, args) {
|
|
212
|
+
return this.serviceLocator.getSyncInstance(token, args);
|
|
213
|
+
}
|
|
214
|
+
invalidate(service, round) {
|
|
215
|
+
return this.serviceLocator.invalidate(service, round);
|
|
216
|
+
}
|
|
217
|
+
ready() {
|
|
218
|
+
return this.serviceLocator.ready();
|
|
219
|
+
}
|
|
220
|
+
makeInstanceName(token, args) {
|
|
221
|
+
return this.serviceLocator.makeInstanceName(token, args);
|
|
222
|
+
}
|
|
187
223
|
};
|
|
188
224
|
function makeProxyServiceLocator(serviceLocator, ctx) {
|
|
189
|
-
|
|
225
|
+
return new ProxyServiceLocator(serviceLocator, ctx);
|
|
190
226
|
}
|
|
191
227
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
const InjectableTokenMeta = Symbol.for("InjectableTokenMeta");
|
|
228
|
+
// src/symbols/injectable-token.mts
|
|
229
|
+
var InjectableTokenMeta = Symbol.for("InjectableTokenMeta");
|
|
195
230
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const InjectorsBase = new Map();
|
|
231
|
+
// src/utils/get-injectors.mts
|
|
232
|
+
var InjectorsBase = /* @__PURE__ */ new Map();
|
|
199
233
|
function getInjectors({ baseLocator }) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
234
|
+
if (InjectorsBase.has(baseLocator)) {
|
|
235
|
+
return InjectorsBase.get(baseLocator);
|
|
236
|
+
}
|
|
237
|
+
let currentLocator = baseLocator;
|
|
238
|
+
function getServiceLocator() {
|
|
239
|
+
if (!currentLocator) {
|
|
240
|
+
throw new Error(
|
|
241
|
+
"[Injector] Service locator is not initialized. Please provide the service locator before using the @Injectable decorator."
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
return currentLocator;
|
|
245
|
+
}
|
|
246
|
+
function provideServiceLocator2(locator) {
|
|
247
|
+
const original = currentLocator;
|
|
248
|
+
currentLocator = locator;
|
|
249
|
+
return original;
|
|
250
|
+
}
|
|
251
|
+
function inject2(token, args) {
|
|
252
|
+
const realToken = token[InjectableTokenMeta] ?? token;
|
|
253
|
+
return getServiceLocator().getOrThrowInstance(realToken, args);
|
|
254
|
+
}
|
|
255
|
+
let promiseCollector = null;
|
|
256
|
+
function wrapSyncInit2(cb) {
|
|
257
|
+
return () => {
|
|
258
|
+
const promises = [];
|
|
259
|
+
const originalPromiseCollector = promiseCollector;
|
|
260
|
+
promiseCollector = (promise) => {
|
|
261
|
+
promises.push(promise);
|
|
262
|
+
};
|
|
263
|
+
const result = cb();
|
|
264
|
+
promiseCollector = originalPromiseCollector;
|
|
265
|
+
return [result, promises];
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
function syncInject2(token, args) {
|
|
269
|
+
const realToken = token[InjectableTokenMeta] ?? token;
|
|
270
|
+
const instance = getServiceLocator().getSyncInstance(realToken, args);
|
|
271
|
+
if (!instance) {
|
|
272
|
+
if (promiseCollector) {
|
|
273
|
+
const promise = getServiceLocator().getInstance(realToken, args);
|
|
274
|
+
promiseCollector(promise);
|
|
275
|
+
} else {
|
|
276
|
+
throw new Error(`[Injector] Cannot initiate ${realToken.toString()}`);
|
|
277
|
+
}
|
|
278
|
+
return new Proxy(
|
|
279
|
+
{},
|
|
280
|
+
{
|
|
281
|
+
get() {
|
|
282
|
+
throw new Error(
|
|
283
|
+
`[Injector] Trying to access ${realToken.toString()} before it's initialized, please use inject() instead of syncInject() or do not use the value outside of class methods`
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
return instance;
|
|
290
|
+
}
|
|
291
|
+
const injectors = {
|
|
292
|
+
inject: inject2,
|
|
293
|
+
syncInject: syncInject2,
|
|
294
|
+
wrapSyncInit: wrapSyncInit2,
|
|
295
|
+
provideServiceLocator: provideServiceLocator2
|
|
296
|
+
};
|
|
297
|
+
InjectorsBase.set(baseLocator, injectors);
|
|
298
|
+
return injectors;
|
|
245
299
|
}
|
|
246
300
|
|
|
247
|
-
|
|
248
|
-
//#region src/utils/get-injectable-token.mts
|
|
301
|
+
// src/utils/get-injectable-token.mts
|
|
249
302
|
function getInjectableToken(target) {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
303
|
+
const token = target[InjectableTokenMeta];
|
|
304
|
+
if (!token) {
|
|
305
|
+
throw new Error(
|
|
306
|
+
`[ServiceLocator] Class ${target.name} is not decorated with @Injectable.`
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
return token;
|
|
253
310
|
}
|
|
254
311
|
|
|
255
|
-
|
|
256
|
-
//#region src/resolve-service.mts
|
|
312
|
+
// src/resolve-service.mts
|
|
257
313
|
async function resolveService(ctx, target, args = []) {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
314
|
+
const { wrapSyncInit: wrapSyncInit2, provideServiceLocator: provideServiceLocator2 } = getInjectors({
|
|
315
|
+
baseLocator: ctx.locator
|
|
316
|
+
});
|
|
317
|
+
const proxyServiceLocator = makeProxyServiceLocator(ctx.locator, ctx);
|
|
318
|
+
const tryLoad = wrapSyncInit2(() => {
|
|
319
|
+
const original = provideServiceLocator2(proxyServiceLocator);
|
|
320
|
+
let result = new target(...args);
|
|
321
|
+
provideServiceLocator2(original);
|
|
322
|
+
return result;
|
|
323
|
+
});
|
|
324
|
+
let [instance, promises] = tryLoad();
|
|
325
|
+
if (promises.length > 0) {
|
|
326
|
+
await Promise.allSettled(promises);
|
|
327
|
+
const newRes = tryLoad();
|
|
328
|
+
instance = newRes[0];
|
|
329
|
+
promises = newRes[1];
|
|
330
|
+
}
|
|
331
|
+
if (promises.length > 0) {
|
|
332
|
+
console.error(`[ServiceLocator] ${target.name} has problem with it's definition.
|
|
275
333
|
|
|
276
334
|
One or more of the dependencies are registered as a InjectableScope.Instance and are used with syncInject.
|
|
277
335
|
|
|
278
336
|
Please use inject instead of syncInject to load those dependencies.`);
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
337
|
+
throw new Error(
|
|
338
|
+
`[ServiceLocator] Service ${target.name} cannot be instantiated.`
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
return instance;
|
|
282
342
|
}
|
|
283
343
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
344
|
+
// src/decorators/injectable.decorator.mts
|
|
345
|
+
function Injectable({
|
|
346
|
+
scope = "Singleton" /* Singleton */,
|
|
347
|
+
type = "Class" /* Class */,
|
|
348
|
+
token,
|
|
349
|
+
registry = globalRegistry
|
|
350
|
+
} = {}) {
|
|
351
|
+
return (target, context) => {
|
|
352
|
+
if (context.kind !== "class") {
|
|
353
|
+
throw new Error(
|
|
354
|
+
"[ServiceLocator] @Injectable decorator can only be used on classes."
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
let injectableToken = token ?? InjectionToken.create(target);
|
|
358
|
+
if (type === "Class" /* Class */) {
|
|
359
|
+
registry.set(
|
|
360
|
+
injectableToken,
|
|
361
|
+
async (ctx, args) => resolveService(ctx, target, [args]),
|
|
362
|
+
scope
|
|
363
|
+
);
|
|
364
|
+
} else if (type === "Factory" /* Factory */) {
|
|
365
|
+
registry.set(
|
|
366
|
+
injectableToken,
|
|
367
|
+
async (ctx, args) => {
|
|
368
|
+
const builder = await resolveService(ctx, target);
|
|
369
|
+
if (typeof builder.create !== "function") {
|
|
370
|
+
throw new Error(
|
|
371
|
+
`[ServiceLocator] Factory ${target.name} does not implement the create method.`
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
return builder.create(ctx, args);
|
|
375
|
+
},
|
|
376
|
+
scope
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
target[InjectableTokenMeta] = injectableToken;
|
|
380
|
+
return target;
|
|
381
|
+
};
|
|
299
382
|
}
|
|
300
383
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
}({});
|
|
384
|
+
// src/errors/errors.enum.mts
|
|
385
|
+
var ErrorsEnum = /* @__PURE__ */ ((ErrorsEnum2) => {
|
|
386
|
+
ErrorsEnum2["InstanceExpired"] = "InstanceExpired";
|
|
387
|
+
ErrorsEnum2["InstanceNotFound"] = "InstanceNotFound";
|
|
388
|
+
ErrorsEnum2["InstanceDestroying"] = "InstanceDestroying";
|
|
389
|
+
ErrorsEnum2["UnknownError"] = "UnknownError";
|
|
390
|
+
ErrorsEnum2["FactoryNotFound"] = "FactoryNotFound";
|
|
391
|
+
ErrorsEnum2["FactoryTokenNotResolved"] = "FactoryTokenNotResolved";
|
|
392
|
+
return ErrorsEnum2;
|
|
393
|
+
})(ErrorsEnum || {});
|
|
312
394
|
|
|
313
|
-
|
|
314
|
-
//#region src/errors/factory-not-found.mts
|
|
395
|
+
// src/errors/factory-not-found.mts
|
|
315
396
|
var FactoryNotFound = class extends Error {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
397
|
+
constructor(name) {
|
|
398
|
+
super(`Factory ${name} not found`);
|
|
399
|
+
this.name = name;
|
|
400
|
+
}
|
|
401
|
+
code = "FactoryNotFound" /* FactoryNotFound */;
|
|
321
402
|
};
|
|
322
403
|
|
|
323
|
-
|
|
324
|
-
//#region src/errors/factory-token-not-resolved.mts
|
|
404
|
+
// src/errors/factory-token-not-resolved.mts
|
|
325
405
|
var FactoryTokenNotResolved = class extends Error {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
406
|
+
code = "FactoryTokenNotResolved" /* FactoryTokenNotResolved */;
|
|
407
|
+
constructor(name) {
|
|
408
|
+
super(`Factory token not resolved: ${name.toString()}`);
|
|
409
|
+
}
|
|
330
410
|
};
|
|
331
411
|
|
|
332
|
-
|
|
333
|
-
//#region src/errors/instance-destroying.mts
|
|
412
|
+
// src/errors/instance-destroying.mts
|
|
334
413
|
var InstanceDestroying = class extends Error {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
414
|
+
constructor(name) {
|
|
415
|
+
super(`Instance ${name} destroying`);
|
|
416
|
+
this.name = name;
|
|
417
|
+
}
|
|
418
|
+
code = "InstanceDestroying" /* InstanceDestroying */;
|
|
340
419
|
};
|
|
341
420
|
|
|
342
|
-
|
|
343
|
-
//#region src/errors/instance-expired.mts
|
|
421
|
+
// src/errors/instance-expired.mts
|
|
344
422
|
var InstanceExpired = class extends Error {
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
423
|
+
constructor(name) {
|
|
424
|
+
super(`Instance ${name} expired`);
|
|
425
|
+
this.name = name;
|
|
426
|
+
}
|
|
427
|
+
code = "InstanceExpired" /* InstanceExpired */;
|
|
350
428
|
};
|
|
351
429
|
|
|
352
|
-
|
|
353
|
-
//#region src/errors/instance-not-found.mts
|
|
430
|
+
// src/errors/instance-not-found.mts
|
|
354
431
|
var InstanceNotFound = class extends Error {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
432
|
+
constructor(name) {
|
|
433
|
+
super(`Instance ${name} not found`);
|
|
434
|
+
this.name = name;
|
|
435
|
+
}
|
|
436
|
+
code = "InstanceNotFound" /* InstanceNotFound */;
|
|
360
437
|
};
|
|
361
438
|
|
|
362
|
-
|
|
363
|
-
//#region src/errors/unknown-error.mts
|
|
439
|
+
// src/errors/unknown-error.mts
|
|
364
440
|
var UnknownError = class extends Error {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
441
|
+
code = "UnknownError" /* UnknownError */;
|
|
442
|
+
parent;
|
|
443
|
+
constructor(message) {
|
|
444
|
+
if (message instanceof Error) {
|
|
445
|
+
super(message.message);
|
|
446
|
+
this.parent = message;
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
super(message);
|
|
450
|
+
}
|
|
375
451
|
};
|
|
376
452
|
|
|
377
|
-
|
|
378
|
-
|
|
453
|
+
// src/interfaces/factory.interface.mts
|
|
454
|
+
var import_zod4 = require("zod");
|
|
455
|
+
|
|
456
|
+
// src/event-emitter.mts
|
|
379
457
|
var EventEmitter = class {
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
458
|
+
listeners = /* @__PURE__ */ new Map();
|
|
459
|
+
on(event, listener) {
|
|
460
|
+
if (!this.listeners.has(event)) {
|
|
461
|
+
this.listeners.set(event, /* @__PURE__ */ new Set());
|
|
462
|
+
}
|
|
463
|
+
this.listeners.get(event).add(listener);
|
|
464
|
+
return () => {
|
|
465
|
+
this.off(event, listener);
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
off(event, listener) {
|
|
469
|
+
if (!this.listeners.has(event)) {
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
this.listeners.get(event).delete(listener);
|
|
473
|
+
if (this.listeners.get(event).size === 0) {
|
|
474
|
+
this.listeners.delete(event);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
once(event, listener) {
|
|
478
|
+
const off = this.on(event, (...args) => {
|
|
479
|
+
off();
|
|
480
|
+
listener(...args);
|
|
481
|
+
});
|
|
482
|
+
return off;
|
|
483
|
+
}
|
|
484
|
+
async emit(event, ...args) {
|
|
485
|
+
if (!this.listeners.has(event)) {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
return Promise.all(Array.from(this.listeners.get(event)).map((listener) => listener(...args)));
|
|
489
|
+
}
|
|
490
|
+
addChannel(ns, event, target) {
|
|
491
|
+
return this.on(event, (...args) => target.emit(ns, event, ...args));
|
|
492
|
+
}
|
|
407
493
|
};
|
|
408
494
|
|
|
409
|
-
|
|
410
|
-
//#region src/service-locator-event-bus.mts
|
|
495
|
+
// src/service-locator-event-bus.mts
|
|
411
496
|
var ServiceLocatorEventBus = class {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
497
|
+
constructor(logger = null) {
|
|
498
|
+
this.logger = logger;
|
|
499
|
+
}
|
|
500
|
+
listeners = /* @__PURE__ */ new Map();
|
|
501
|
+
on(ns, event, listener) {
|
|
502
|
+
this.logger?.debug(`[ServiceLocatorEventBus]#on(): ns:${ns} event:${event}`);
|
|
503
|
+
if (!this.listeners.has(ns)) {
|
|
504
|
+
this.listeners.set(ns, /* @__PURE__ */ new Map());
|
|
505
|
+
}
|
|
506
|
+
const nsEvents = this.listeners.get(ns);
|
|
507
|
+
if (!nsEvents.has(event)) {
|
|
508
|
+
nsEvents.set(event, /* @__PURE__ */ new Set());
|
|
509
|
+
}
|
|
510
|
+
nsEvents.get(event).add(listener);
|
|
511
|
+
return () => {
|
|
512
|
+
nsEvents.get(event).delete(listener);
|
|
513
|
+
if (nsEvents.get(event)?.size === 0) {
|
|
514
|
+
nsEvents.delete(event);
|
|
515
|
+
}
|
|
516
|
+
if (nsEvents.size === 0) {
|
|
517
|
+
this.listeners.delete(ns);
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
async emit(key, event) {
|
|
522
|
+
if (!this.listeners.has(key)) {
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
const events = this.listeners.get(key);
|
|
526
|
+
const preEvent = `pre:${event}`;
|
|
527
|
+
const postEvent = `post:${event}`;
|
|
528
|
+
this.logger?.debug(`[ServiceLocatorEventBus]#emit(): ${key}:${preEvent}`);
|
|
529
|
+
await Promise.allSettled(
|
|
530
|
+
[...events.get(preEvent) ?? []].map((listener) => listener(preEvent))
|
|
531
|
+
).then((results) => {
|
|
532
|
+
results.filter((result) => result.status === "rejected").forEach((result) => {
|
|
533
|
+
this.logger?.warn(
|
|
534
|
+
`[ServiceLocatorEventBus]#emit(): ${key}:${preEvent} rejected with`,
|
|
535
|
+
result.reason
|
|
536
|
+
);
|
|
537
|
+
});
|
|
538
|
+
});
|
|
539
|
+
this.logger?.debug(`[ServiceLocatorEventBus]#emit(): ${key}:${event}`);
|
|
540
|
+
const res = await Promise.allSettled(
|
|
541
|
+
[...events.get(event) ?? []].map((listener) => listener(event))
|
|
542
|
+
).then((results) => {
|
|
543
|
+
const res2 = results.filter((result) => result.status === "rejected").map((result) => {
|
|
544
|
+
this.logger?.warn(
|
|
545
|
+
`[ServiceLocatorEventBus]#emit(): ${key}:${event} rejected with`,
|
|
546
|
+
result.reason
|
|
547
|
+
);
|
|
548
|
+
return result;
|
|
549
|
+
});
|
|
550
|
+
if (res2.length > 0) {
|
|
551
|
+
return Promise.reject(res2);
|
|
552
|
+
}
|
|
553
|
+
return results;
|
|
554
|
+
});
|
|
555
|
+
this.logger?.debug(`[ServiceLocatorEventBus]#emit(): ${key}:${postEvent}`);
|
|
556
|
+
await Promise.allSettled(
|
|
557
|
+
[...events.get(postEvent) ?? []].map((listener) => listener(postEvent))
|
|
558
|
+
).then((results) => {
|
|
559
|
+
results.filter((result) => result.status === "rejected").forEach((result) => {
|
|
560
|
+
this.logger?.warn(
|
|
561
|
+
`[ServiceLocatorEventBus]#emit(): ${key}:${postEvent} rejected with`,
|
|
562
|
+
result.reason
|
|
563
|
+
);
|
|
564
|
+
});
|
|
565
|
+
});
|
|
566
|
+
return res;
|
|
567
|
+
}
|
|
456
568
|
};
|
|
457
569
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
}({});
|
|
570
|
+
// src/service-locator-instance-holder.mts
|
|
571
|
+
var ServiceLocatorInstanceHolderKind = /* @__PURE__ */ ((ServiceLocatorInstanceHolderKind2) => {
|
|
572
|
+
ServiceLocatorInstanceHolderKind2["Instance"] = "instance";
|
|
573
|
+
ServiceLocatorInstanceHolderKind2["Factory"] = "factory";
|
|
574
|
+
ServiceLocatorInstanceHolderKind2["AbstractFactory"] = "abstractFactory";
|
|
575
|
+
return ServiceLocatorInstanceHolderKind2;
|
|
576
|
+
})(ServiceLocatorInstanceHolderKind || {});
|
|
577
|
+
var ServiceLocatorInstanceHolderStatus = /* @__PURE__ */ ((ServiceLocatorInstanceHolderStatus2) => {
|
|
578
|
+
ServiceLocatorInstanceHolderStatus2["Created"] = "created";
|
|
579
|
+
ServiceLocatorInstanceHolderStatus2["Creating"] = "creating";
|
|
580
|
+
ServiceLocatorInstanceHolderStatus2["Destroying"] = "destroying";
|
|
581
|
+
return ServiceLocatorInstanceHolderStatus2;
|
|
582
|
+
})(ServiceLocatorInstanceHolderStatus || {});
|
|
472
583
|
|
|
473
|
-
|
|
474
|
-
//#region src/service-locator-manager.mts
|
|
584
|
+
// src/service-locator-manager.mts
|
|
475
585
|
var ServiceLocatorManager = class {
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
586
|
+
constructor(logger = null) {
|
|
587
|
+
this.logger = logger;
|
|
588
|
+
}
|
|
589
|
+
instancesHolders = /* @__PURE__ */ new Map();
|
|
590
|
+
get(name) {
|
|
591
|
+
const holder = this.instancesHolders.get(name);
|
|
592
|
+
if (holder) {
|
|
593
|
+
if (holder.ttl !== Infinity) {
|
|
594
|
+
const now = Date.now();
|
|
595
|
+
if (now - holder.createdAt > holder.ttl) {
|
|
596
|
+
this.logger?.log(
|
|
597
|
+
`[ServiceLocatorManager]#getInstanceHolder() TTL expired for ${holder.name}`
|
|
598
|
+
);
|
|
599
|
+
return [new InstanceExpired(holder.name), holder];
|
|
600
|
+
}
|
|
601
|
+
} else if (holder.status === "destroying" /* Destroying */) {
|
|
602
|
+
this.logger?.log(
|
|
603
|
+
`[ServiceLocatorManager]#getInstanceHolder() Instance ${holder.name} is destroying`
|
|
604
|
+
);
|
|
605
|
+
return [new InstanceDestroying(holder.name), holder];
|
|
606
|
+
}
|
|
607
|
+
return [void 0, holder];
|
|
608
|
+
} else {
|
|
609
|
+
this.logger?.log(
|
|
610
|
+
`[ServiceLocatorManager]#getInstanceHolder() Instance ${name} not found`
|
|
611
|
+
);
|
|
612
|
+
return [new InstanceNotFound(name)];
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
set(name, holder) {
|
|
616
|
+
this.instancesHolders.set(name, holder);
|
|
617
|
+
}
|
|
618
|
+
has(name) {
|
|
619
|
+
const [error, holder] = this.get(name);
|
|
620
|
+
if (!error) {
|
|
621
|
+
return [void 0, true];
|
|
622
|
+
}
|
|
623
|
+
if (["InstanceExpired" /* InstanceExpired */, "InstanceDestroying" /* InstanceDestroying */].includes(
|
|
624
|
+
error.code
|
|
625
|
+
)) {
|
|
626
|
+
return [error];
|
|
627
|
+
}
|
|
628
|
+
return [void 0, !!holder];
|
|
629
|
+
}
|
|
630
|
+
delete(name) {
|
|
631
|
+
return this.instancesHolders.delete(name);
|
|
632
|
+
}
|
|
633
|
+
filter(predicate) {
|
|
634
|
+
return new Map(
|
|
635
|
+
[...this.instancesHolders].filter(
|
|
636
|
+
([key, value]) => predicate(value, key)
|
|
637
|
+
)
|
|
638
|
+
);
|
|
639
|
+
}
|
|
514
640
|
};
|
|
515
641
|
|
|
516
|
-
|
|
517
|
-
//#region src/service-locator.mts
|
|
642
|
+
// src/service-locator.mts
|
|
518
643
|
var ServiceLocator = class {
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
644
|
+
constructor(registry = globalRegistry, logger = null) {
|
|
645
|
+
this.registry = registry;
|
|
646
|
+
this.logger = logger;
|
|
647
|
+
this.eventBus = new ServiceLocatorEventBus(logger);
|
|
648
|
+
this.manager = new ServiceLocatorManager(logger);
|
|
649
|
+
}
|
|
650
|
+
eventBus;
|
|
651
|
+
manager;
|
|
652
|
+
getEventBus() {
|
|
653
|
+
return this.eventBus;
|
|
654
|
+
}
|
|
655
|
+
storeInstance(instance, token, args) {
|
|
656
|
+
const instanceName = this.getInstanceIdentifier(token, args);
|
|
657
|
+
this.manager.set(instanceName, {
|
|
658
|
+
name: instanceName,
|
|
659
|
+
instance,
|
|
660
|
+
status: "created" /* Created */,
|
|
661
|
+
kind: "instance" /* Instance */,
|
|
662
|
+
createdAt: Date.now(),
|
|
663
|
+
ttl: Infinity,
|
|
664
|
+
deps: [],
|
|
665
|
+
destroyListeners: [],
|
|
666
|
+
effects: [],
|
|
667
|
+
destroyPromise: null,
|
|
668
|
+
creationPromise: null
|
|
669
|
+
});
|
|
670
|
+
this.notifyListeners(instanceName);
|
|
671
|
+
}
|
|
672
|
+
removeInstance(token, args) {
|
|
673
|
+
const instanceName = this.getInstanceIdentifier(token, args);
|
|
674
|
+
return this.invalidate(instanceName);
|
|
675
|
+
}
|
|
676
|
+
resolveTokenArgs(token, args) {
|
|
677
|
+
let realArgs = args;
|
|
678
|
+
if (token instanceof BoundInjectionToken) {
|
|
679
|
+
realArgs = token.value;
|
|
680
|
+
} else if (token instanceof FactoryInjectionToken) {
|
|
681
|
+
if (token.resolved) {
|
|
682
|
+
realArgs = token.value;
|
|
683
|
+
} else {
|
|
684
|
+
return [new FactoryTokenNotResolved(token.name)];
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
if (!token.schema) {
|
|
688
|
+
return [void 0, realArgs];
|
|
689
|
+
}
|
|
690
|
+
const validatedArgs = token.schema?.safeParse(realArgs);
|
|
691
|
+
if (validatedArgs && !validatedArgs.success) {
|
|
692
|
+
this.logger?.error(
|
|
693
|
+
`[ServiceLocator]#resolveTokenArgs(): Error validating args for ${token.name.toString()}`,
|
|
694
|
+
validatedArgs.error
|
|
695
|
+
);
|
|
696
|
+
return [new UnknownError(validatedArgs.error)];
|
|
697
|
+
}
|
|
698
|
+
return [void 0, validatedArgs?.data];
|
|
699
|
+
}
|
|
700
|
+
getInstanceIdentifier(token, args) {
|
|
701
|
+
const [err, realArgs] = this.resolveTokenArgs(
|
|
702
|
+
token,
|
|
703
|
+
args
|
|
704
|
+
);
|
|
705
|
+
if (err) {
|
|
706
|
+
throw err;
|
|
707
|
+
}
|
|
708
|
+
return this.makeInstanceName(token, realArgs);
|
|
709
|
+
}
|
|
710
|
+
async getInstance(token, args) {
|
|
711
|
+
const [err, realArgs] = this.resolveTokenArgs(token, args);
|
|
712
|
+
if (err instanceof UnknownError) {
|
|
713
|
+
return [err];
|
|
714
|
+
} else if (err instanceof FactoryTokenNotResolved && token instanceof FactoryInjectionToken) {
|
|
715
|
+
this.logger?.log(
|
|
716
|
+
`[ServiceLocator]#getInstance() Factory token not resolved, resolving it`
|
|
717
|
+
);
|
|
718
|
+
await token.resolve();
|
|
719
|
+
return this.getInstance(token);
|
|
720
|
+
}
|
|
721
|
+
const instanceName = this.makeInstanceName(token, realArgs);
|
|
722
|
+
const [error, holder] = this.manager.get(instanceName);
|
|
723
|
+
if (!error) {
|
|
724
|
+
if (holder.status === "creating" /* Creating */) {
|
|
725
|
+
return holder.creationPromise;
|
|
726
|
+
} else if (holder.status === "destroying" /* Destroying */) {
|
|
727
|
+
return [new UnknownError("InstanceDestroying" /* InstanceDestroying */)];
|
|
728
|
+
}
|
|
729
|
+
return [void 0, holder.instance];
|
|
730
|
+
}
|
|
731
|
+
switch (error.code) {
|
|
732
|
+
case "InstanceDestroying" /* InstanceDestroying */:
|
|
733
|
+
this.logger?.log(
|
|
734
|
+
`[ServiceLocator]#getInstance() TTL expired for ${holder?.name}`
|
|
735
|
+
);
|
|
736
|
+
await holder?.destroyPromise;
|
|
737
|
+
return this.getInstance(token, args);
|
|
738
|
+
case "InstanceExpired" /* InstanceExpired */:
|
|
739
|
+
this.logger?.log(
|
|
740
|
+
`[ServiceLocator]#getInstance() TTL expired for ${holder?.name}`
|
|
741
|
+
);
|
|
742
|
+
await this.invalidate(instanceName);
|
|
743
|
+
return this.getInstance(token, args);
|
|
744
|
+
case "InstanceNotFound" /* InstanceNotFound */:
|
|
745
|
+
break;
|
|
746
|
+
default:
|
|
747
|
+
return [error];
|
|
748
|
+
}
|
|
749
|
+
return this.createInstance(instanceName, token, realArgs);
|
|
750
|
+
}
|
|
751
|
+
async getOrThrowInstance(token, args) {
|
|
752
|
+
const [error, instance] = await this.getInstance(token, args);
|
|
753
|
+
if (error) {
|
|
754
|
+
throw error;
|
|
755
|
+
}
|
|
756
|
+
return instance;
|
|
757
|
+
}
|
|
758
|
+
notifyListeners(name, event = "create") {
|
|
759
|
+
this.logger?.log(
|
|
760
|
+
`[ServiceLocator]#notifyListeners() Notifying listeners for ${name} with event ${event}`
|
|
761
|
+
);
|
|
762
|
+
return this.eventBus.emit(name, event);
|
|
763
|
+
}
|
|
764
|
+
async createInstance(instanceName, token, args) {
|
|
765
|
+
this.logger?.log(
|
|
766
|
+
`[ServiceLocator]#createInstance() Creating instance for ${instanceName}`
|
|
767
|
+
);
|
|
768
|
+
let realToken = token instanceof BoundInjectionToken || token instanceof FactoryInjectionToken ? token.token : token;
|
|
769
|
+
if (this.registry.has(realToken)) {
|
|
770
|
+
return this.resolveInstance(instanceName, realToken, args);
|
|
771
|
+
} else {
|
|
772
|
+
return [new FactoryNotFound(realToken.name.toString())];
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
resolveInstance(instanceName, token, args) {
|
|
776
|
+
this.logger?.log(
|
|
777
|
+
`[ServiceLocator]#resolveInstance(): Creating instance for ${instanceName} from abstract factory`
|
|
778
|
+
);
|
|
779
|
+
const ctx = this.createFactoryContext(instanceName);
|
|
780
|
+
let { factory, scope } = this.registry.get(token);
|
|
781
|
+
const holder = {
|
|
782
|
+
name: instanceName,
|
|
783
|
+
instance: null,
|
|
784
|
+
status: "creating" /* Creating */,
|
|
785
|
+
kind: "abstractFactory" /* AbstractFactory */,
|
|
786
|
+
// @ts-expect-error TS2322 This is correct type
|
|
787
|
+
creationPromise: factory(ctx, args).then(async (instance) => {
|
|
788
|
+
holder.instance = instance;
|
|
789
|
+
holder.status = "created" /* Created */;
|
|
790
|
+
holder.deps = ctx.getDependencies();
|
|
791
|
+
holder.destroyListeners = ctx.getDestroyListeners();
|
|
792
|
+
holder.ttl = ctx.getTtl();
|
|
793
|
+
if (holder.deps.length > 0) {
|
|
794
|
+
this.logger?.log(
|
|
795
|
+
`[ServiceLocator]#createInstanceFromAbstractFactory(): Adding subscriptions for ${instanceName} dependencies for their invalidations: ${holder.deps.join(
|
|
796
|
+
", "
|
|
797
|
+
)}`
|
|
798
|
+
);
|
|
799
|
+
holder.deps.forEach((dependency) => {
|
|
800
|
+
holder.destroyListeners.push(
|
|
801
|
+
this.eventBus.on(
|
|
802
|
+
dependency,
|
|
803
|
+
"destroy",
|
|
804
|
+
() => this.invalidate(instanceName)
|
|
805
|
+
)
|
|
806
|
+
);
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
if (holder.ttl === 0 || scope === "Instance" /* Instance */) {
|
|
810
|
+
await this.invalidate(instanceName);
|
|
811
|
+
}
|
|
812
|
+
await this.notifyListeners(instanceName);
|
|
813
|
+
return [void 0, instance];
|
|
814
|
+
}).catch((error) => {
|
|
815
|
+
this.logger?.error(
|
|
816
|
+
`[ServiceLocator]#createInstanceFromAbstractFactory(): Error creating instance for ${instanceName}`,
|
|
817
|
+
error
|
|
818
|
+
);
|
|
819
|
+
return [new UnknownError(error)];
|
|
820
|
+
}),
|
|
821
|
+
effects: [],
|
|
822
|
+
deps: [],
|
|
823
|
+
destroyListeners: [],
|
|
824
|
+
createdAt: Date.now(),
|
|
825
|
+
ttl: Infinity
|
|
826
|
+
};
|
|
827
|
+
if (scope === "Singleton" /* Singleton */) {
|
|
828
|
+
this.logger?.debug(
|
|
829
|
+
`[ServiceLocator]#resolveInstance(): Setting instance for ${instanceName}`
|
|
830
|
+
);
|
|
831
|
+
this.manager.set(instanceName, holder);
|
|
832
|
+
}
|
|
833
|
+
return holder.creationPromise;
|
|
834
|
+
}
|
|
835
|
+
createFactoryContext(instanceName) {
|
|
836
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
837
|
+
const destroyListeners = /* @__PURE__ */ new Set();
|
|
838
|
+
const self = this;
|
|
839
|
+
function invalidate(name = instanceName) {
|
|
840
|
+
return self.invalidate(name);
|
|
841
|
+
}
|
|
842
|
+
function addEffect(listener) {
|
|
843
|
+
destroyListeners.add(listener);
|
|
844
|
+
}
|
|
845
|
+
let ttl = Infinity;
|
|
846
|
+
function setTtl(value) {
|
|
847
|
+
ttl = value;
|
|
848
|
+
}
|
|
849
|
+
function getTtl() {
|
|
850
|
+
return ttl;
|
|
851
|
+
}
|
|
852
|
+
function on(key, event, listener) {
|
|
853
|
+
destroyListeners.add(self.eventBus.on(key, event, listener));
|
|
854
|
+
}
|
|
855
|
+
return {
|
|
856
|
+
// @ts-expect-error This is correct type
|
|
857
|
+
async inject(token, args) {
|
|
858
|
+
let injectionToken = token;
|
|
859
|
+
if (typeof token === "function") {
|
|
860
|
+
injectionToken = getInjectableToken(token);
|
|
861
|
+
}
|
|
862
|
+
if (injectionToken) {
|
|
863
|
+
const [err, validatedArgs] = self.resolveTokenArgs(
|
|
864
|
+
injectionToken,
|
|
865
|
+
args
|
|
866
|
+
);
|
|
867
|
+
if (err) {
|
|
868
|
+
throw err;
|
|
869
|
+
}
|
|
870
|
+
const instanceName2 = self.makeInstanceName(token, validatedArgs);
|
|
871
|
+
dependencies.add(instanceName2);
|
|
872
|
+
return self.getOrThrowInstance(injectionToken, args);
|
|
873
|
+
}
|
|
874
|
+
throw new Error(
|
|
875
|
+
`[ServiceLocator]#inject(): Invalid token type: ${typeof token}. Expected a class or an InjectionToken.`
|
|
876
|
+
);
|
|
877
|
+
},
|
|
878
|
+
invalidate,
|
|
879
|
+
on,
|
|
880
|
+
getDependencies: () => Array.from(dependencies),
|
|
881
|
+
addEffect,
|
|
882
|
+
getDestroyListeners: () => Array.from(destroyListeners),
|
|
883
|
+
setTtl,
|
|
884
|
+
getTtl,
|
|
885
|
+
locator: self
|
|
886
|
+
};
|
|
887
|
+
}
|
|
888
|
+
getSyncInstance(token, args) {
|
|
889
|
+
const [err, realArgs] = this.resolveTokenArgs(token, args);
|
|
890
|
+
if (err) {
|
|
891
|
+
return null;
|
|
892
|
+
}
|
|
893
|
+
const instanceName = this.makeInstanceName(token, realArgs);
|
|
894
|
+
const [error, holder] = this.manager.get(instanceName);
|
|
895
|
+
if (error) {
|
|
896
|
+
return null;
|
|
897
|
+
}
|
|
898
|
+
return holder.instance;
|
|
899
|
+
}
|
|
900
|
+
invalidate(service, round = 1) {
|
|
901
|
+
this.logger?.log(
|
|
902
|
+
`[ServiceLocator]#invalidate(): Starting Invalidating process of ${service}`
|
|
903
|
+
);
|
|
904
|
+
const toInvalidate = this.manager.filter(
|
|
905
|
+
(holder) => holder.name === service || holder.deps.includes(service)
|
|
906
|
+
);
|
|
907
|
+
const promises = [];
|
|
908
|
+
for (const [key, holder] of toInvalidate.entries()) {
|
|
909
|
+
if (holder.status === "destroying" /* Destroying */) {
|
|
910
|
+
this.logger?.trace(
|
|
911
|
+
`[ServiceLocator]#invalidate(): ${key} is already being destroyed`
|
|
912
|
+
);
|
|
913
|
+
promises.push(holder.destroyPromise);
|
|
914
|
+
continue;
|
|
915
|
+
}
|
|
916
|
+
if (holder.status === "creating" /* Creating */) {
|
|
917
|
+
this.logger?.trace(
|
|
918
|
+
`[ServiceLocator]#invalidate(): ${key} is being created, waiting for creation to finish`
|
|
919
|
+
);
|
|
920
|
+
promises.push(
|
|
921
|
+
holder.creationPromise?.then(() => {
|
|
922
|
+
if (round > 3) {
|
|
923
|
+
this.logger?.error(
|
|
924
|
+
`[ServiceLocator]#invalidate(): ${key} creation is triggering a new invalidation round, but it is still not created`
|
|
925
|
+
);
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
return this.invalidate(key, round + 1);
|
|
929
|
+
})
|
|
930
|
+
);
|
|
931
|
+
continue;
|
|
932
|
+
}
|
|
933
|
+
holder.status = "destroying" /* Destroying */;
|
|
934
|
+
this.logger?.log(
|
|
935
|
+
`[ServiceLocator]#invalidate(): Invalidating ${key} and notifying listeners`
|
|
936
|
+
);
|
|
937
|
+
holder.destroyPromise = Promise.all(
|
|
938
|
+
holder.destroyListeners.map((listener) => listener())
|
|
939
|
+
).then(async () => {
|
|
940
|
+
this.manager.delete(key);
|
|
941
|
+
await this.notifyListeners(key, "destroy");
|
|
942
|
+
});
|
|
943
|
+
promises.push(holder.destroyPromise);
|
|
944
|
+
}
|
|
945
|
+
return Promise.all(promises);
|
|
946
|
+
}
|
|
947
|
+
async ready() {
|
|
948
|
+
return Promise.all(
|
|
949
|
+
Array.from(this.manager.filter(() => true)).map(([, holder]) => {
|
|
950
|
+
if (holder.status === "creating" /* Creating */) {
|
|
951
|
+
return holder.creationPromise?.then(() => null);
|
|
952
|
+
}
|
|
953
|
+
if (holder.status === "destroying" /* Destroying */) {
|
|
954
|
+
return holder.destroyPromise.then(() => null);
|
|
955
|
+
}
|
|
956
|
+
return Promise.resolve(null);
|
|
957
|
+
})
|
|
958
|
+
).then(() => null);
|
|
959
|
+
}
|
|
960
|
+
makeInstanceName(token, args) {
|
|
961
|
+
const formattedArgs = args ? ":" + Object.entries(args ?? {}).sort(([keyA], [keyB]) => keyA.localeCompare(keyB)).map(([key, value]) => {
|
|
962
|
+
if (typeof value === "function") {
|
|
963
|
+
return `${key}=fn_${value.name}(${value.length})`;
|
|
964
|
+
}
|
|
965
|
+
if (typeof value === "symbol") {
|
|
966
|
+
return `${key}=${value.toString()}`;
|
|
967
|
+
}
|
|
968
|
+
return `${key}=${JSON.stringify(value).slice(0, 40)}`;
|
|
969
|
+
}).join(",").replaceAll(/"/g, "").replaceAll(/:/g, "=") : "";
|
|
970
|
+
return `${token.toString()}${formattedArgs}`;
|
|
971
|
+
}
|
|
745
972
|
};
|
|
746
973
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
const globalServiceLocator = new ServiceLocator();
|
|
974
|
+
// src/injector.mts
|
|
975
|
+
var globalServiceLocator = new ServiceLocator(globalRegistry);
|
|
750
976
|
function getGlobalServiceLocator() {
|
|
751
|
-
|
|
752
|
-
|
|
977
|
+
if (!globalServiceLocator) {
|
|
978
|
+
throw new Error(
|
|
979
|
+
"[ServiceLocator] Service locator is not initialized. Please provide the service locator before using the @Injectable decorator."
|
|
980
|
+
);
|
|
981
|
+
}
|
|
982
|
+
return globalServiceLocator;
|
|
753
983
|
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
exports
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
984
|
+
var values = getInjectors({
|
|
985
|
+
baseLocator: globalServiceLocator
|
|
986
|
+
});
|
|
987
|
+
var inject = values.inject;
|
|
988
|
+
var syncInject = values.syncInject;
|
|
989
|
+
var wrapSyncInit = values.wrapSyncInit;
|
|
990
|
+
var provideServiceLocator = values.provideServiceLocator;
|
|
991
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
992
|
+
0 && (module.exports = {
|
|
993
|
+
BoundInjectionToken,
|
|
994
|
+
ErrorsEnum,
|
|
995
|
+
EventEmitter,
|
|
996
|
+
FactoryInjectionToken,
|
|
997
|
+
FactoryNotFound,
|
|
998
|
+
FactoryTokenNotResolved,
|
|
999
|
+
Injectable,
|
|
1000
|
+
InjectableScope,
|
|
1001
|
+
InjectableTokenMeta,
|
|
1002
|
+
InjectableType,
|
|
1003
|
+
InjectionToken,
|
|
1004
|
+
InjectorsBase,
|
|
1005
|
+
InstanceDestroying,
|
|
1006
|
+
InstanceExpired,
|
|
1007
|
+
InstanceNotFound,
|
|
1008
|
+
ProxyServiceLocator,
|
|
1009
|
+
Registry,
|
|
1010
|
+
ServiceLocator,
|
|
1011
|
+
ServiceLocatorEventBus,
|
|
1012
|
+
ServiceLocatorInstanceHolderKind,
|
|
1013
|
+
ServiceLocatorInstanceHolderStatus,
|
|
1014
|
+
ServiceLocatorManager,
|
|
1015
|
+
UnknownError,
|
|
1016
|
+
getGlobalServiceLocator,
|
|
1017
|
+
getInjectableToken,
|
|
1018
|
+
getInjectors,
|
|
1019
|
+
globalRegistry,
|
|
1020
|
+
inject,
|
|
1021
|
+
makeProxyServiceLocator,
|
|
1022
|
+
provideServiceLocator,
|
|
1023
|
+
resolveService,
|
|
1024
|
+
syncInject,
|
|
1025
|
+
wrapSyncInit
|
|
1026
|
+
});
|
|
1027
|
+
//# sourceMappingURL=index.js.map
|