@moostjs/otel 0.4.6 → 0.4.8

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/dist/index.cjs CHANGED
@@ -2,7 +2,11 @@
2
2
 
3
3
  var api = require('@opentelemetry/api');
4
4
  var moost = require('moost');
5
+ var crypto = require('crypto');
6
+ var node_async_hooks = require('node:async_hooks');
7
+ var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
5
8
 
9
+ const spanStack = [];
6
10
  function useOtelContext() {
7
11
  const store = moost.useAsyncEventContext().store('otel');
8
12
  const getSpan = () => store.get('span');
@@ -22,23 +26,42 @@ function useOtelContext() {
22
26
  }
23
27
  return {};
24
28
  };
29
+ const pushSpan = (span) => {
30
+ const activeSpan = api.trace.getActiveSpan();
31
+ if (activeSpan) {
32
+ const origEnd = activeSpan.end;
33
+ Object.assign(activeSpan, {
34
+ end: (t) => {
35
+ popSpan();
36
+ const i = spanStack.indexOf(activeSpan);
37
+ if (i >= 0) {
38
+ spanStack.splice(i, 1);
39
+ }
40
+ origEnd.apply(span, [t]);
41
+ },
42
+ });
43
+ spanStack.push(activeSpan);
44
+ }
45
+ api.trace.setSpan(api.context.active(), span);
46
+ };
47
+ const popSpan = () => {
48
+ const span = spanStack.pop();
49
+ if (span) {
50
+ api.trace.setSpan(api.context.active(), span);
51
+ }
52
+ };
25
53
  return {
26
54
  trace: api.trace,
27
55
  withChildSpan: (name, cb, opts) => {
28
- const parentSpan = getSpan();
29
- if (parentSpan) {
30
- const tracer = api.trace.getTracer('moost-tracer');
31
- const span = tracer.startSpan(name, opts);
32
- return () => api.context.with(api.trace.setSpan(api.context.active(), span), () => cb());
33
- }
34
- else {
35
- return cb();
36
- }
56
+ const tracer = api.trace.getTracer('moost-tracer');
57
+ const span = tracer.startSpan(name, opts);
58
+ return () => api.context.with(api.trace.setSpan(api.context.active(), span), cb);
37
59
  },
38
60
  getSpan,
39
61
  getSpanContext,
40
62
  getPropagationHeaders,
41
63
  registerSpan: (span) => store.set('span', span),
64
+ pushSpan,
42
65
  };
43
66
  }
44
67
  function useTrace() {
@@ -55,59 +78,1107 @@ function useOtelPropagation() {
55
78
  };
56
79
  }
57
80
 
58
- function enableOtelForMoost() {
59
- moost.eventContextHooks.onStartEvent((eventType) => {
60
- if (eventType === 'init') {
61
- return;
81
+ const meter = api.metrics.getMeter('moost-meter');
82
+ const moostMetrics = {
83
+ httpRequestCount: meter.createCounter('http.server.requests', {
84
+ description: 'The number of HTTP requests received',
85
+ }),
86
+ httpResponseCount: meter.createCounter('http.server.responses', {
87
+ description: 'The number of HTTP responses sent',
88
+ }),
89
+ httpActiveRequests: meter.createUpDownCounter('http.server.active_requests', {
90
+ description: 'The number of active HTTP requests',
91
+ }),
92
+ httpRequestSize: meter.createHistogram('http.server.request.size', {
93
+ description: 'The size of HTTP request bodies',
94
+ }),
95
+ httpResponseSize: meter.createHistogram('http.server.response.size', {
96
+ description: 'The size of HTTP response bodies',
97
+ }),
98
+ httpErrorCount: meter.createCounter('http.server.errors', {
99
+ description: 'The number of HTTP requests that resulted in an error',
100
+ }),
101
+ moostEventCount: meter.createCounter('moost.events.count', {
102
+ description: 'The number of HTTP requests received',
103
+ }),
104
+ moostActiveEvents: meter.createUpDownCounter('moost.events.active', {
105
+ description: 'The number of active HTTP requests',
106
+ }),
107
+ moostErrorCount: meter.createCounter('moost.events.errors', {
108
+ description: 'The number of HTTP requests that resulted in an error',
109
+ }),
110
+ };
111
+
112
+ const tracer = api.trace.getTracer('moost-tracer');
113
+ class SpanInjector extends moost.ContextInjector {
114
+ with(name, attributes, cb) {
115
+ const fn = typeof attributes === 'function' ? attributes : cb;
116
+ const attrs = typeof attributes === 'object' ? attributes : undefined;
117
+ if (name === 'Event:start' && attrs?.eventType) {
118
+ return this.startEvent(name, attrs.eventType, fn);
62
119
  }
120
+ else if (name !== 'Event:start') {
121
+ if (this.getIgnoreSpan()) {
122
+ return fn();
123
+ }
124
+ else {
125
+ const span = tracer.startSpan(name, {
126
+ attributes: attrs,
127
+ });
128
+ return this.withSpan(span, fn, {
129
+ rootSpan: false,
130
+ endSpan: true,
131
+ });
132
+ }
133
+ }
134
+ return fn();
135
+ }
136
+ patchRsponse() {
137
+ const res = this.getResponse();
138
+ if (res) {
139
+ const originalWriteHead = res.writeHead;
140
+ Object.assign(res, {
141
+ writeHead: (arg0, arg1, arg2) => {
142
+ res._statusCode = arg0;
143
+ const headers = typeof arg2 === 'object' ? arg2 : typeof arg1 === 'object' ? arg1 : undefined;
144
+ res._contentLength = headers?.['content-length'] ? Number(headers['content-length']) : 0;
145
+ return originalWriteHead.apply(res, [arg0, arg1, arg2]);
146
+ },
147
+ });
148
+ }
149
+ }
150
+ startEvent(name, eventType, cb) {
63
151
  const { registerSpan } = useOtelContext();
64
- let span;
152
+ let span = api.trace.getActiveSpan();
65
153
  if (eventType === 'HTTP') {
66
- span = api.trace.getSpan(api.context.active());
154
+ this.patchRsponse();
67
155
  }
68
156
  else {
69
- const tracer = api.trace.getTracer('moost-tracer');
70
157
  span = tracer.startSpan(`${eventType} Event`);
71
158
  }
72
159
  if (span) {
73
160
  registerSpan(span);
161
+ return this.withSpan(span, cb, {
162
+ rootSpan: true,
163
+ endSpan: eventType !== 'HTTP',
164
+ });
74
165
  }
75
- });
76
- moost.eventContextHooks.onEndEvent((eventType, abortReason) => {
77
- if (eventType === 'init') {
78
- return;
166
+ return cb();
167
+ }
168
+ getEventType() {
169
+ return moost.useAsyncEventContext().getCtx().event.type;
170
+ }
171
+ getIgnoreSpan() {
172
+ const { getMethodMeta, getControllerMeta } = moost.useControllerContext();
173
+ const cMeta = getControllerMeta();
174
+ const mMeta = getMethodMeta();
175
+ return cMeta?.otelIgnoreSpan || mMeta?.otelIgnoreSpan;
176
+ }
177
+ getControllerHandlerMeta() {
178
+ const { getMethod, getMethodMeta, getController, getControllerMeta, getRoute } = moost.useControllerContext();
179
+ const methodName = getMethod();
180
+ const cMeta = getControllerMeta();
181
+ const mMeta = getMethodMeta();
182
+ return {
183
+ ignoreMeter: cMeta?.otelIgnoreMeter || mMeta?.otelIgnoreMeter,
184
+ ignoreSpan: cMeta?.otelIgnoreSpan || mMeta?.otelIgnoreSpan,
185
+ attrs: {
186
+ 'moost.controller': moost.getConstructor(getController()).name,
187
+ 'moost.handler': methodName,
188
+ 'moost.handler_description': mMeta?.description,
189
+ 'moost.handler_label': mMeta?.label,
190
+ 'moost.handler_id': mMeta?.id,
191
+ 'moost.ignore': cMeta?.otelIgnoreSpan || mMeta?.otelIgnoreSpan,
192
+ 'moost.route': getRoute(),
193
+ 'moost.event_type': this.getEventType(),
194
+ },
195
+ };
196
+ }
197
+ hook(name, route) {
198
+ moost.useAsyncEventContext().store('otel').set('route', route);
199
+ const chm = this.getControllerHandlerMeta();
200
+ if (!chm.ignoreMeter) {
201
+ this.startEventMetrics(chm.attrs, route);
79
202
  }
80
203
  const { getSpan } = useOtelContext();
81
204
  const span = getSpan();
82
205
  if (span) {
83
- const { getMethod, getMethodMeta, getController } = moost.useControllerContext();
84
- const methodName = getMethod();
85
- const methodMeta = getMethodMeta();
86
- span.setAttributes({
87
- 'custom.event_type': eventType,
88
- 'custom.event_description': methodMeta?.description || methodMeta?.label || methodName,
89
- 'moost.controller': moost.getConstructor(getController()).name,
90
- 'moost.handler': methodName,
91
- });
92
- if (abortReason) {
93
- span.recordException(new Error(abortReason));
94
- span.setStatus({ code: api.SpanStatusCode.ERROR, message: abortReason });
95
- }
96
- if (eventType === 'HTTP') {
97
- const req = moost.useAsyncEventContext()
98
- .store('event')
99
- .get('req');
100
- span.updateName(`${req?.method || ''} ${methodMeta?.id || methodMeta?.label || methodName}`);
206
+ span.setAttributes(chm.attrs);
207
+ if (chm.attrs['moost.event_type'] === 'HTTP') {
208
+ span.updateName(`${this.getRequest()?.method || ''} ${route || '<unresolved>'}`);
101
209
  }
102
210
  else {
103
- span.updateName(`${methodMeta?.label || methodName}`);
211
+ span.updateName(`${chm.attrs['moost.event_type']} ${route || '<unresolved>'}`);
212
+ }
213
+ }
214
+ }
215
+ withSpan(span, cb, opts) {
216
+ let result;
217
+ let exception;
218
+ const endSpan = (error) => {
219
+ if (error) {
220
+ span.recordException(error);
221
+ }
222
+ if (opts.rootSpan) {
223
+ const chm = this.getControllerHandlerMeta();
224
+ if (!chm.ignoreMeter) {
225
+ this.endEventMetrics(chm.attrs, error);
226
+ }
227
+ }
228
+ if (opts.endSpan) {
104
229
  span.end();
105
230
  }
231
+ };
232
+ api.context.with(api.trace.setSpan(api.context.active(), span), () => {
233
+ try {
234
+ result = cb();
235
+ }
236
+ catch (error) {
237
+ exception = error;
238
+ endSpan(exception);
239
+ }
240
+ });
241
+ const ret = result;
242
+ if (!exception) {
243
+ if (ret && ret instanceof Promise) {
244
+ ret
245
+ .then(r => {
246
+ endSpan();
247
+ return r;
248
+ })
249
+ .catch(error => {
250
+ endSpan(error);
251
+ });
252
+ }
253
+ else {
254
+ endSpan();
255
+ }
106
256
  }
257
+ return ret;
258
+ }
259
+ startEventMetrics(a, route) {
260
+ if (a['moost.event_type'] === 'HTTP') {
261
+ const req = this.getRequest();
262
+ const attrs = {
263
+ ...a,
264
+ route,
265
+ url: req?.url,
266
+ };
267
+ moostMetrics.httpRequestCount.add(1, attrs);
268
+ moostMetrics.httpActiveRequests.add(1, attrs);
269
+ }
270
+ const attrs = {
271
+ ...a,
272
+ route,
273
+ };
274
+ moostMetrics.moostEventCount.add(1, attrs);
275
+ moostMetrics.moostActiveEvents.add(1, attrs);
276
+ }
277
+ endEventMetrics(a, error) {
278
+ const route = moost.useAsyncEventContext().store('otel').get('route');
279
+ if (a['moost.event_type'] === 'HTTP') {
280
+ const req = this.getRequest();
281
+ const res = this.getResponse();
282
+ const attrs = {
283
+ ...a,
284
+ route,
285
+ url: req?.url,
286
+ };
287
+ moostMetrics.httpActiveRequests.add(-1, attrs);
288
+ if (error) {
289
+ moostMetrics.httpErrorCount.add(1, attrs);
290
+ }
291
+ moostMetrics.httpRequestSize.record(req?.socket.bytesRead || 0, attrs);
292
+ moostMetrics.httpResponseSize.record(res?._contentLength || 0, attrs);
293
+ moostMetrics.httpResponseCount.add(1, { ...attrs, status: res?._statusCode });
294
+ }
295
+ const attrs = {
296
+ ...a,
297
+ route,
298
+ };
299
+ moostMetrics.moostActiveEvents.add(-1, attrs);
300
+ if (error) {
301
+ moostMetrics.moostErrorCount.add(1, attrs);
302
+ }
303
+ }
304
+ getRequest() {
305
+ return moost.useAsyncEventContext().store('event').get('req');
306
+ }
307
+ getResponse() {
308
+ return moost.useAsyncEventContext()
309
+ .store('event')
310
+ .get('res');
311
+ }
312
+ }
313
+
314
+ function enableOtelForMoost() {
315
+ moost.replaceContextInjector(new SpanInjector());
316
+ }
317
+
318
+ function getConstructor$1(instance) {
319
+ return isConstructor(instance) ?
320
+ instance : instance.constructor ?
321
+ instance.constructor : Object.getPrototypeOf(instance).constructor;
322
+ }
323
+ function isConstructor(v) {
324
+ return typeof v === 'function' && Object.getOwnPropertyNames(v).includes('prototype') && !Object.getOwnPropertyNames(v).includes('caller') && !!v.name;
325
+ }
326
+
327
+ const classMetadata = new WeakMap();
328
+ const paramMetadata = new WeakMap();
329
+ const root = typeof global === 'object' ? global : typeof self === 'object' ? self : {};
330
+ function getMetaObject(target, prop) {
331
+ const isParam = typeof prop !== 'undefined';
332
+ const metadata = isParam ? paramMetadata : classMetadata;
333
+ const targetKey = getConstructor$1(target);
334
+ let meta = metadata.get(targetKey);
335
+ if (!meta) {
336
+ meta = {};
337
+ metadata.set(targetKey, meta);
338
+ }
339
+ if (isParam) {
340
+ meta = (meta[prop] =
341
+ meta[prop] || {});
342
+ }
343
+ return meta;
344
+ }
345
+ const _reflect = {
346
+ getOwnMetadata(key, target, prop) {
347
+ return getMetaObject(target, prop)[key];
348
+ },
349
+ defineMetadata(key, data, target, prop) {
350
+ const meta = getMetaObject(target, prop);
351
+ meta[key] = data;
352
+ },
353
+ metadata(key, data) {
354
+ return ((target, propKey) => {
355
+ Reflect$1.defineMetadata(key, data, target, propKey);
356
+ });
357
+ },
358
+ };
359
+ if (!root.Reflect) {
360
+ root.Reflect = _reflect;
361
+ }
362
+ else {
363
+ const funcs = [
364
+ 'getOwnMetadata',
365
+ 'defineMetadata',
366
+ 'metadata',
367
+ ];
368
+ const target = root.Reflect;
369
+ for (const func of funcs) {
370
+ if (typeof target[func] !== 'function') {
371
+ Object.defineProperty(target, func, { configurable: true, writable: true, value: _reflect[func] });
372
+ }
373
+ }
374
+ }
375
+ const Reflect$1 = _reflect;
376
+
377
+ const Reflect = (global === null || global === void 0 ? void 0 : global.Reflect) || (self === null || self === void 0 ? void 0 : self.Reflect) || Reflect$1;
378
+ class Mate {
379
+ constructor(workspace, options = {}) {
380
+ this.workspace = workspace;
381
+ this.options = options;
382
+ this.logger = options.logger || console;
383
+ }
384
+ set(args, key, value, isArray) {
385
+ var _a;
386
+ let level = 'CLASS';
387
+ const newArgs = args.level === 'CLASS' ? { target: args.target }
388
+ : args.level === 'PROP' ? { target: args.target, propKey: args.propKey }
389
+ : args;
390
+ let meta = (Reflect.getOwnMetadata(this.workspace, newArgs.target, newArgs.propKey) || {});
391
+ if (newArgs.propKey && this.options.readReturnType && !meta.returnType && args.descriptor) {
392
+ meta.returnType = Reflect.getOwnMetadata('design:returntype', newArgs.target, newArgs.propKey);
393
+ }
394
+ if (newArgs.propKey && this.options.readType && !meta.type) {
395
+ meta.type = Reflect.getOwnMetadata('design:type', newArgs.target, newArgs.propKey);
396
+ }
397
+ const { index } = newArgs;
398
+ const cb = typeof key === 'function' ? key : undefined;
399
+ let data = meta;
400
+ if (!data.params) {
401
+ data.params = (_a = Reflect.getOwnMetadata('design:paramtypes', newArgs.target, newArgs.propKey)) === null || _a === void 0 ? void 0 : _a.map((f) => ({ type: f }));
402
+ }
403
+ if (typeof index === 'number') {
404
+ level = 'PARAM';
405
+ data.params = data.params || [];
406
+ data.params[index] = data.params[index] || {
407
+ type: undefined,
408
+ };
409
+ if (cb) {
410
+ data.params[index] = cb(data.params[index], level, args.propKey, typeof args.index === 'number' ? args.index : undefined);
411
+ }
412
+ else {
413
+ data = data.params[index];
414
+ }
415
+ }
416
+ else if (!index && !args.descriptor && args.propKey && this.options.collectPropKeys && args.level !== 'CLASS') {
417
+ this.set({ ...args, level: 'CLASS' }, (meta) => {
418
+ if (!meta.properties) {
419
+ meta.properties = [args.propKey];
420
+ }
421
+ else if (!meta.properties.includes(args.propKey)) {
422
+ meta.properties.push(args.propKey);
423
+ }
424
+ return meta;
425
+ });
426
+ }
427
+ level = typeof index === 'number' ? 'PARAM' : newArgs.propKey && newArgs.descriptor ? 'METHOD' : newArgs.propKey ? 'PROP' : 'CLASS';
428
+ if (typeof key !== 'function') {
429
+ if (isArray) {
430
+ const newArray = (data[key] || []);
431
+ if (!Array.isArray(newArray)) {
432
+ this.logger.error('Mate.add (isArray=true) called for non-array metadata');
433
+ }
434
+ newArray.unshift(value);
435
+ data[key] = newArray;
436
+ }
437
+ else {
438
+ data[key] = value;
439
+ }
440
+ }
441
+ else if (cb && typeof index !== 'number') {
442
+ meta = cb(data, level, args.propKey, typeof args.index === 'number' ? args.index : undefined);
443
+ }
444
+ Reflect.defineMetadata(this.workspace, meta, newArgs.target, newArgs.propKey);
445
+ }
446
+ read(target, propKey) {
447
+ var _a;
448
+ const isConstr = isConstructor(target);
449
+ const constructor = isConstr ? target : getConstructor$1(target);
450
+ const proto = constructor.prototype;
451
+ let ownMeta = Reflect.getOwnMetadata(this.workspace, typeof propKey === 'string' ? proto : constructor, propKey);
452
+ if (ownMeta && propKey === undefined && ownMeta.params === undefined) {
453
+ const parent = Object.getPrototypeOf(constructor);
454
+ if (typeof parent === 'function' &&
455
+ parent !== fnProto &&
456
+ parent !== constructor) {
457
+ ownMeta.params = (_a = this.read(parent)) === null || _a === void 0 ? void 0 : _a.params;
458
+ }
459
+ }
460
+ if (this.options.inherit) {
461
+ const inheritFn = typeof this.options.inherit === 'function'
462
+ ? this.options.inherit
463
+ : undefined;
464
+ let shouldInherit = this.options.inherit;
465
+ if (inheritFn) {
466
+ if (typeof propKey === 'string') {
467
+ const classMeta = Reflect.getOwnMetadata(this.workspace, constructor);
468
+ shouldInherit = inheritFn(classMeta, ownMeta, 'PROP', propKey);
469
+ }
470
+ else {
471
+ shouldInherit = inheritFn(ownMeta, ownMeta, 'CLASS');
472
+ }
473
+ }
474
+ if (shouldInherit) {
475
+ const parent = Object.getPrototypeOf(constructor);
476
+ if (typeof parent === 'function' &&
477
+ parent !== fnProto &&
478
+ parent !== constructor) {
479
+ const inheritedMeta = (this.read(parent, propKey) ||
480
+ {});
481
+ const ownParams = ownMeta === null || ownMeta === void 0 ? void 0 : ownMeta.params;
482
+ ownMeta = { ...inheritedMeta, ...ownMeta };
483
+ if (typeof propKey === 'string' &&
484
+ ownParams &&
485
+ (inheritedMeta === null || inheritedMeta === void 0 ? void 0 : inheritedMeta.params)) {
486
+ for (let i = 0; i < ownParams.length; i++) {
487
+ if (typeof (inheritedMeta === null || inheritedMeta === void 0 ? void 0 : inheritedMeta.params[i]) !==
488
+ 'undefined') {
489
+ const ownParam = ownParams[i];
490
+ if (ownMeta.params &&
491
+ inheritFn &&
492
+ inheritFn(ownMeta, ownParam, 'PARAM', typeof propKey === 'string'
493
+ ? propKey
494
+ : undefined)) {
495
+ ownMeta.params[i] = {
496
+ ...inheritedMeta === null || inheritedMeta === void 0 ? void 0 : inheritedMeta.params[i],
497
+ ...ownParams[i],
498
+ };
499
+ }
500
+ }
501
+ }
502
+ }
503
+ }
504
+ }
505
+ }
506
+ return ownMeta;
507
+ }
508
+ apply(...decorators) {
509
+ return ((target, propKey, descriptor) => {
510
+ for (const d of decorators) {
511
+ d(target, propKey, descriptor);
512
+ }
513
+ });
514
+ }
515
+ decorate(key, value, isArray, level) {
516
+ return ((target, propKey, descriptor) => {
517
+ const args = {
518
+ target,
519
+ propKey,
520
+ descriptor: typeof descriptor === 'number' ? undefined : descriptor,
521
+ index: typeof descriptor === 'number' ? descriptor : undefined,
522
+ level,
523
+ };
524
+ this.set(args, key, value, isArray);
525
+ });
526
+ }
527
+ decorateConditional(ccb) {
528
+ return ((target, propKey, descriptor) => {
529
+ const hasIndex = typeof descriptor === 'number';
530
+ const decoratorLevel = hasIndex ? 'PARAM' : propKey && descriptor ? 'METHOD' : propKey ? 'PROP' : 'CLASS';
531
+ const d = ccb(decoratorLevel);
532
+ if (d) {
533
+ d(target, propKey, descriptor);
534
+ }
535
+ });
536
+ }
537
+ decorateClass(key, value, isArray) {
538
+ return this.decorate(key, value, isArray, 'CLASS');
539
+ }
540
+ }
541
+ const fnProto = Object.getPrototypeOf(Function);
542
+
543
+ const defaultLevels = [
544
+ 'fatal',
545
+ 'error',
546
+ 'warn',
547
+ 'log',
548
+ 'info',
549
+ 'debug',
550
+ 'trace',
551
+ ];
552
+ const defaultMappedLevels = new Map();
553
+ defaultLevels.forEach((type, level) => defaultMappedLevels.set(type, level));
554
+
555
+ function attachHook(target, opts, name) {
556
+ Object.defineProperty(target, name || 'value', {
557
+ get: opts.get,
558
+ set: opts.set,
107
559
  });
560
+ return target;
561
+ }
562
+
563
+ const asyncStorage = new node_async_hooks.AsyncLocalStorage();
564
+ function useAsyncEventContext(expectedTypes) {
565
+ let cc = asyncStorage.getStore();
566
+ if (!cc) {
567
+ throw new Error('Event context does not exist at this point.');
568
+ }
569
+ if (expectedTypes || typeof expectedTypes === 'string') {
570
+ const type = cc.event.type;
571
+ const types = typeof expectedTypes === 'string' ? [expectedTypes] : expectedTypes;
572
+ if (!types.includes(type)) {
573
+ if (cc.parentCtx?.event.type && types.includes(cc.parentCtx.event.type)) {
574
+ cc = cc.parentCtx;
575
+ }
576
+ else {
577
+ throw new Error(`Event context type mismatch: expected ${types
578
+ .map(t => `"${t}"`)
579
+ .join(', ')}, received "${type}"`);
580
+ }
581
+ }
582
+ }
583
+ return _getCtxHelpers(cc);
584
+ }
585
+ function _getCtxHelpers(cc) {
586
+ function store(key) {
587
+ const obj = {
588
+ value: null,
589
+ hook,
590
+ init,
591
+ set: setNested,
592
+ get: getNested,
593
+ has: hasNested,
594
+ del: delNested,
595
+ entries,
596
+ clear,
597
+ };
598
+ attachHook(obj, {
599
+ set: v => {
600
+ set(key, v);
601
+ },
602
+ get: () => get(key),
603
+ });
604
+ function init(key2, getter) {
605
+ if (hasNested(key2)) {
606
+ return getNested(key2);
607
+ }
608
+ return setNested(key2, getter());
609
+ }
610
+ function hook(key2) {
611
+ const obj = {
612
+ value: null,
613
+ isDefined: null,
614
+ };
615
+ attachHook(obj, {
616
+ set: v => setNested(key2, v),
617
+ get: () => getNested(key2),
618
+ });
619
+ attachHook(obj, {
620
+ get: () => hasNested(key2),
621
+ }, 'isDefined');
622
+ return obj;
623
+ }
624
+ function setNested(key2, v) {
625
+ if (obj.value === undefined) {
626
+ obj.value = {};
627
+ }
628
+ obj.value[key2] = v;
629
+ return v;
630
+ }
631
+ function delNested(key2) {
632
+ setNested(key2, undefined);
633
+ }
634
+ function getNested(key2) {
635
+ return (obj.value || {})[key2];
636
+ }
637
+ function hasNested(key2) {
638
+ return (obj.value || {})[key2] !== undefined;
639
+ }
640
+ function entries() {
641
+ return Object.entries(obj.value || {});
642
+ }
643
+ function clear() {
644
+ obj.value = {};
645
+ }
646
+ return obj;
647
+ }
648
+ function getCtx() {
649
+ return cc;
650
+ }
651
+ function get(key) {
652
+ return getCtx()[key];
653
+ }
654
+ function set(key, v) {
655
+ getCtx()[key] = v;
656
+ }
657
+ const hasParentCtx = () => !!cc.parentCtx;
658
+ return {
659
+ getCtx,
660
+ store,
661
+ getStore: get,
662
+ setStore: set,
663
+ setParentCtx: (parentCtx) => {
664
+ cc.parentCtx = parentCtx;
665
+ },
666
+ hasParentCtx,
667
+ getParentCtx: () => {
668
+ if (!hasParentCtx()) {
669
+ throw new Error('Parent context is not available');
670
+ }
671
+ return _getCtxHelpers(cc.parentCtx);
672
+ },
673
+ };
674
+ }
675
+
676
+ function useEventId() {
677
+ const { store } = useAsyncEventContext();
678
+ const { init } = store('event');
679
+ const getId = () => init('id', () => crypto.randomUUID());
680
+ return { getId };
681
+ }
682
+
683
+ function getConstructor(instance) {
684
+ return Object.getPrototypeOf(instance).constructor;
685
+ }
686
+
687
+ const globalRegistry = {};
688
+ const UNDEFINED = Symbol('undefined');
689
+ class Infact {
690
+ constructor(options) {
691
+ this.options = options;
692
+ this.registry = {};
693
+ this.instanceRegistries = new WeakMap();
694
+ this.scopes = {};
695
+ this._silent = false;
696
+ this.logger = options.logger || console;
697
+ }
698
+ setLogger(logger) {
699
+ this.logger = logger;
700
+ }
701
+ silent(value = 'logs') {
702
+ this._silent = value;
703
+ }
704
+ registerScope(scopeId) {
705
+ if (!this.scopes[scopeId]) {
706
+ this.scopes[scopeId] = {};
707
+ }
708
+ }
709
+ unregisterScope(scopeId) {
710
+ delete this.scopes[scopeId];
711
+ }
712
+ getForInstance(instance, classConstructor, opts) {
713
+ const registries = this.getInstanceRegistries(instance);
714
+ return this.get(classConstructor, {
715
+ ...opts,
716
+ provide: registries.provide || {},
717
+ replace: registries.replace,
718
+ customData: registries.customData,
719
+ });
720
+ }
721
+ async get(classConstructor, opts, optional = false) {
722
+ const result = await this._get(classConstructor, opts, optional);
723
+ if (result) {
724
+ const { instance, mergedProvide, replace } = result;
725
+ if (this.options.storeProvideRegByInstance) {
726
+ this.setInstanceRegistries(instance, mergedProvide, replace, opts === null || opts === void 0 ? void 0 : opts.customData);
727
+ }
728
+ return instance;
729
+ }
730
+ return undefined;
731
+ }
732
+ setInstanceRegistries(instance, provide, replace, customData) {
733
+ this.instanceRegistries.set(instance, { provide, replace, customData });
734
+ }
735
+ getInstanceRegistries(instance) {
736
+ return this.instanceRegistries.get(instance) || {};
737
+ }
738
+ async _get(classConstructor, opts, optional) {
739
+ const hierarchy = (opts === null || opts === void 0 ? void 0 : opts.hierarchy) || [];
740
+ const provide = opts === null || opts === void 0 ? void 0 : opts.provide;
741
+ const replace = opts === null || opts === void 0 ? void 0 : opts.replace;
742
+ const syncContextFn = opts === null || opts === void 0 ? void 0 : opts.syncContextFn;
743
+ hierarchy.push(classConstructor.name);
744
+ let classMeta;
745
+ let instanceKey = Symbol.for(classConstructor);
746
+ if (replace && replace[instanceKey]) {
747
+ classConstructor = replace === null || replace === void 0 ? void 0 : replace[instanceKey];
748
+ instanceKey = Symbol.for(classConstructor);
749
+ }
750
+ try {
751
+ classMeta = this.options.describeClass(classConstructor);
752
+ }
753
+ catch (e) {
754
+ throw this.panicOwnError(`Could not instantiate "${classConstructor.name}". ` +
755
+ `An error occored on "describeClass" function.\n${e.message}`, hierarchy);
756
+ }
757
+ if (!classMeta || !classMeta.injectable) {
758
+ if (provide && provide[instanceKey]) {
759
+ syncContextFn && syncContextFn(classMeta);
760
+ return {
761
+ instance: await getProvidedValue(provide[instanceKey]),
762
+ mergedProvide: provide,
763
+ replace,
764
+ };
765
+ }
766
+ if (!optional) {
767
+ throw this.panicOwnError(`Could not instantiate Injectable "${classConstructor.name}". ` +
768
+ 'Please check if the class is injectable or if you properly typed arguments.', hierarchy);
769
+ }
770
+ else {
771
+ return undefined;
772
+ }
773
+ }
774
+ if (classMeta.scopeId && classMeta.global) {
775
+ throw this.panicOwnError(`Could not instantiate scoped Injectable "${classConstructor.name}" for scope "${classMeta.scopeId}". ` +
776
+ 'The scoped Injectable is not supported for Global scope.', hierarchy);
777
+ }
778
+ if (classMeta.scopeId && !this.scopes[classMeta.scopeId]) {
779
+ throw this.panicOwnError(`Could not instantiate scoped Injectable "${classConstructor.name}" for scope "${classMeta.scopeId}". ` +
780
+ 'The requested scope isn\'t registered.', hierarchy);
781
+ }
782
+ const scope = classMeta.scopeId
783
+ ? this.scopes[classMeta.scopeId]
784
+ : {};
785
+ const mergedProvide = {
786
+ ...(provide || {}),
787
+ ...(classMeta.provide || {}),
788
+ };
789
+ if (mergedProvide[instanceKey]) {
790
+ syncContextFn && syncContextFn(classMeta);
791
+ return {
792
+ instance: await getProvidedValue(mergedProvide[instanceKey]),
793
+ mergedProvide,
794
+ replace,
795
+ };
796
+ }
797
+ if (!this.registry[instanceKey] &&
798
+ !globalRegistry[instanceKey] &&
799
+ !scope[instanceKey]) {
800
+ const registry = classMeta.scopeId
801
+ ? scope
802
+ : classMeta.global
803
+ ? globalRegistry
804
+ : this.registry;
805
+ const params = classMeta.constructorParams || [];
806
+ const isCircular = !!params.find((p) => !!p.circular);
807
+ if (isCircular) {
808
+ registry[instanceKey] = Object.create(classConstructor.prototype);
809
+ }
810
+ const resolvedParams = [];
811
+ for (let i = 0; i < params.length; i++) {
812
+ const param = params[i];
813
+ if (param.inject) {
814
+ if (mergedProvide && mergedProvide[param.inject]) {
815
+ resolvedParams[i] = getProvidedValue(mergedProvide[param.inject]);
816
+ }
817
+ else if (param.nullable || param.optional) {
818
+ resolvedParams[i] = UNDEFINED;
819
+ }
820
+ else {
821
+ throw this.panicOwnError(`Could not inject ${JSON.stringify(param.inject)} to "${classConstructor.name}" to argument ${param.label
822
+ ? `labeled as "${param.label}"`
823
+ : `with index ${i}`}`, hierarchy);
824
+ }
825
+ }
826
+ else if (this.options.resolveParam) {
827
+ resolvedParams[i] = this.options.resolveParam({
828
+ classMeta,
829
+ classConstructor,
830
+ index: i,
831
+ paramMeta: param,
832
+ customData: opts === null || opts === void 0 ? void 0 : opts.customData,
833
+ });
834
+ }
835
+ }
836
+ for (let i = 0; i < resolvedParams.length; i++) {
837
+ const rp = resolvedParams[i];
838
+ if (rp &&
839
+ rp !== UNDEFINED &&
840
+ typeof rp.then === 'function') {
841
+ try {
842
+ syncContextFn && syncContextFn(classMeta);
843
+ resolvedParams[i] = await rp;
844
+ }
845
+ catch (e) {
846
+ const param = params[i];
847
+ throw this.panic(e, `Could not inject "${param.type.name}" to "${classConstructor.name}" ` +
848
+ `constructor at index ${i}${param.label ? ` (${param.label})` : ''}. An exception occured.`, hierarchy);
849
+ }
850
+ }
851
+ }
852
+ for (let i = 0; i < params.length; i++) {
853
+ const param = params[i];
854
+ if (typeof resolvedParams[i] === 'undefined') {
855
+ if (param.type === undefined && !param.circular) {
856
+ if (this._silent === false) {
857
+ this.logger.warn(`${classConstructor.name}.constructor() expects argument ${param.label
858
+ ? `labeled as "${param.label}"`
859
+ : `#${i}`} that is undefined. This might happen when Circular Dependency occurs. To handle Circular Dependencies please specify circular meta for param.`);
860
+ }
861
+ }
862
+ else if (param.type === undefined && param.circular) {
863
+ param.type = param.circular();
864
+ }
865
+ if (typeof param.type === 'function') {
866
+ if ([String, Number, Date, Array].includes(param.type)) {
867
+ if (!param.nullable && !param.optional) {
868
+ throw this.panicOwnError(`Could not inject "${param.type
869
+ .name}" to "${classConstructor.name}" ` +
870
+ `constructor at index ${i}${param.label
871
+ ? ` (${param.label})`
872
+ : ''}. The param was not resolved to a value.`, hierarchy);
873
+ }
874
+ }
875
+ resolvedParams[i] = this.get(param.type, {
876
+ provide: mergedProvide,
877
+ replace,
878
+ hierarchy,
879
+ syncContextFn,
880
+ customData: opts === null || opts === void 0 ? void 0 : opts.customData,
881
+ }, param.optional || param.nullable);
882
+ }
883
+ }
884
+ if (resolvedParams[i] === UNDEFINED) {
885
+ resolvedParams[i] = undefined;
886
+ }
887
+ }
888
+ for (let i = 0; i < resolvedParams.length; i++) {
889
+ const rp = resolvedParams[i];
890
+ if (rp && typeof rp.then === 'function') {
891
+ try {
892
+ syncContextFn && syncContextFn(classMeta);
893
+ resolvedParams[i] = await rp;
894
+ }
895
+ catch (e) {
896
+ const param = params[i];
897
+ throw this.panic(e, `Could not inject "${param.type.name}" to "${classConstructor.name}" ` +
898
+ `constructor at index ${i}${param.label ? ` (${param.label})` : ''}. An exception occured.`, hierarchy);
899
+ }
900
+ }
901
+ }
902
+ const instance = new classConstructor(...resolvedParams);
903
+ if (isCircular) {
904
+ Object.assign(registry[instanceKey], instance);
905
+ }
906
+ else {
907
+ registry[instanceKey] = instance;
908
+ }
909
+ if (this.options.describeProp &&
910
+ this.options.resolveProp &&
911
+ classMeta.properties &&
912
+ classMeta.properties.length) {
913
+ const resolvedProps = {};
914
+ for (const prop of classMeta.properties) {
915
+ const initialValue = instance[prop];
916
+ let propMeta;
917
+ try {
918
+ propMeta = this.options.describeProp(classConstructor, prop);
919
+ }
920
+ catch (e) {
921
+ throw this.panic(e, `Could not process prop "${prop}" of "${classConstructor.name}". ` +
922
+ `An error occored on "describeProp" function.\n${e.message}`, hierarchy);
923
+ }
924
+ if (propMeta) {
925
+ try {
926
+ resolvedProps[prop] = this.options.resolveProp({
927
+ classMeta,
928
+ classConstructor,
929
+ initialValue,
930
+ key: prop,
931
+ instance,
932
+ propMeta,
933
+ customData: opts === null || opts === void 0 ? void 0 : opts.customData,
934
+ });
935
+ }
936
+ catch (e) {
937
+ throw this.panic(e, `Could not inject prop "${prop}" to "${classConstructor.name}". ` +
938
+ 'An exception occured: ' +
939
+ e.message, hierarchy);
940
+ }
941
+ }
942
+ }
943
+ for (const [prop, value] of Object.entries(resolvedProps)) {
944
+ try {
945
+ syncContextFn && syncContextFn(classMeta);
946
+ resolvedProps[prop] = value
947
+ ? await value
948
+ : value;
949
+ }
950
+ catch (e) {
951
+ throw this.panic(e, `Could not inject prop "${prop}" to "${classConstructor.name}". ` +
952
+ 'An exception occured: ' +
953
+ e.message, hierarchy);
954
+ }
955
+ }
956
+ Object.assign(instance, resolvedProps);
957
+ }
958
+ if (this._silent === false) {
959
+ this.logger.info(`Class "${'' +
960
+ classConstructor.name +
961
+ '' +
962
+ ''}" instantiated with: ${''}[${resolvedParams
963
+ .map((p) => {
964
+ switch (typeof p) {
965
+ case 'number':
966
+ case 'boolean':
967
+ return p;
968
+ case 'string':
969
+ return `"${''}...${''}"`;
970
+ case 'object':
971
+ if (getConstructor(p))
972
+ return getConstructor(p).name;
973
+ return '{}';
974
+ default:
975
+ return '*';
976
+ }
977
+ })
978
+ .join(', ')}]`);
979
+ }
980
+ }
981
+ hierarchy.pop();
982
+ syncContextFn && syncContextFn(classMeta);
983
+ return {
984
+ instance: await (scope[instanceKey] ||
985
+ this.registry[instanceKey] ||
986
+ globalRegistry[instanceKey]),
987
+ mergedProvide,
988
+ replace,
989
+ };
990
+ }
991
+ panic(origError, text, hierarchy) {
992
+ if (this._silent === true) ;
993
+ else {
994
+ this.logger.error(text +
995
+ (hierarchy
996
+ ? '\nHierarchy:\n' + hierarchy.join(' -> ')
997
+ : ''));
998
+ }
999
+ return origError;
1000
+ }
1001
+ panicOwnError(text, hierarchy) {
1002
+ const e = new Error(text + (hierarchy ? '\nHierarchy:\n' + hierarchy.join(' -> ') : ''));
1003
+ if (this._silent === true) {
1004
+ return e;
1005
+ }
1006
+ else {
1007
+ this.logger.error(e);
1008
+ return e;
1009
+ }
1010
+ }
1011
+ }
1012
+ function getProvidedValue(meta) {
1013
+ if (!meta.resolved) {
1014
+ meta.resolved = true;
1015
+ meta.value = meta.fn();
1016
+ }
1017
+ return meta.value;
1018
+ }
1019
+
1020
+ async function runPipes(pipes, initialValue, metas, level) {
1021
+ let v = initialValue;
1022
+ for (const pipe of pipes) {
1023
+ v = await pipe.handler(v, metas, level);
1024
+ }
1025
+ return v;
1026
+ }
1027
+
1028
+ const METADATA_WORKSPACE = 'moost';
1029
+ const moostMate = new Mate(METADATA_WORKSPACE, {
1030
+ readType: true,
1031
+ readReturnType: true,
1032
+ collectPropKeys: true,
1033
+ inherit(classMeta, targetMeta, level) {
1034
+ if (level === 'CLASS') {
1035
+ return !!classMeta?.inherit;
1036
+ }
1037
+ if (level === 'PROP') {
1038
+ return !!targetMeta?.inherit || !!(classMeta?.inherit && !targetMeta);
1039
+ }
1040
+ return !!targetMeta?.inherit;
1041
+ },
1042
+ });
1043
+ function getMoostMate() {
1044
+ return moostMate;
1045
+ }
1046
+
1047
+ getNewMoostInfact();
1048
+ function getNewMoostInfact() {
1049
+ return new Infact({
1050
+ describeClass(classConstructor) {
1051
+ const meta = getMoostMate().read(classConstructor);
1052
+ return {
1053
+ injectable: !!meta?.injectable,
1054
+ global: false,
1055
+ constructorParams: meta?.params || [],
1056
+ provide: meta?.provide,
1057
+ properties: meta?.properties || [],
1058
+ scopeId: meta?.injectable === 'FOR_EVENT' ? useEventId().getId() : undefined,
1059
+ };
1060
+ },
1061
+ resolveParam({ paramMeta, classMeta, customData, classConstructor, index }) {
1062
+ if (paramMeta && customData?.pipes) {
1063
+ return runPipes(customData.pipes, undefined, {
1064
+ paramMeta,
1065
+ type: classConstructor,
1066
+ key: 'constructor',
1067
+ classMeta: classMeta,
1068
+ index,
1069
+ targetMeta: paramMeta,
1070
+ }, 'PARAM');
1071
+ }
1072
+ },
1073
+ describeProp(classConstructor, key) {
1074
+ const meta = getMoostMate().read(classConstructor, key);
1075
+ return meta;
1076
+ },
1077
+ resolveProp({ instance, key, initialValue, propMeta, classMeta, customData, classConstructor, }) {
1078
+ if (propMeta && customData?.pipes) {
1079
+ return runPipes(customData.pipes, initialValue, {
1080
+ instance,
1081
+ type: classConstructor,
1082
+ key,
1083
+ propMeta,
1084
+ targetMeta: propMeta,
1085
+ classMeta: classMeta,
1086
+ }, 'PROP');
1087
+ }
1088
+ },
1089
+ storeProvideRegByInstance: true,
1090
+ });
1091
+ }
1092
+
1093
+ getMoostMate().decorate(meta => {
1094
+ if (!meta.injectable) {
1095
+ meta.injectable = true;
1096
+ }
1097
+ return meta;
1098
+ });
1099
+
1100
+ var TInterceptorPriority;
1101
+ (function (TInterceptorPriority) {
1102
+ TInterceptorPriority[TInterceptorPriority["BEFORE_ALL"] = 0] = "BEFORE_ALL";
1103
+ TInterceptorPriority[TInterceptorPriority["BEFORE_GUARD"] = 1] = "BEFORE_GUARD";
1104
+ TInterceptorPriority[TInterceptorPriority["GUARD"] = 2] = "GUARD";
1105
+ TInterceptorPriority[TInterceptorPriority["AFTER_GUARD"] = 3] = "AFTER_GUARD";
1106
+ TInterceptorPriority[TInterceptorPriority["INTERCEPTOR"] = 4] = "INTERCEPTOR";
1107
+ TInterceptorPriority[TInterceptorPriority["CATCH_ERROR"] = 5] = "CATCH_ERROR";
1108
+ TInterceptorPriority[TInterceptorPriority["AFTER_ALL"] = 6] = "AFTER_ALL";
1109
+ })(TInterceptorPriority || (TInterceptorPriority = {}));
1110
+
1111
+ var TPipePriority;
1112
+ (function (TPipePriority) {
1113
+ TPipePriority[TPipePriority["BEFORE_RESOLVE"] = 0] = "BEFORE_RESOLVE";
1114
+ TPipePriority[TPipePriority["RESOLVE"] = 1] = "RESOLVE";
1115
+ TPipePriority[TPipePriority["AFTER_RESOLVE"] = 2] = "AFTER_RESOLVE";
1116
+ TPipePriority[TPipePriority["BEFORE_TRANSFORM"] = 3] = "BEFORE_TRANSFORM";
1117
+ TPipePriority[TPipePriority["TRANSFORM"] = 4] = "TRANSFORM";
1118
+ TPipePriority[TPipePriority["AFTER_TRANSFORM"] = 5] = "AFTER_TRANSFORM";
1119
+ TPipePriority[TPipePriority["BEFORE_VALIDATE"] = 6] = "BEFORE_VALIDATE";
1120
+ TPipePriority[TPipePriority["VALIDATE"] = 7] = "VALIDATE";
1121
+ TPipePriority[TPipePriority["AFTER_VALIDATE"] = 8] = "AFTER_VALIDATE";
1122
+ })(TPipePriority || (TPipePriority = {}));
1123
+
1124
+ function definePipeFn(fn, priority = TPipePriority.TRANSFORM) {
1125
+ fn.priority = priority;
1126
+ return fn;
1127
+ }
1128
+
1129
+ const resolvePipe = definePipeFn((_value, metas, level) => {
1130
+ const resolver = metas.targetMeta?.resolver;
1131
+ if (resolver) {
1132
+ return resolver(metas, level);
1133
+ }
1134
+ return undefined;
1135
+ }, TPipePriority.RESOLVE);
1136
+
1137
+ [
1138
+ {
1139
+ handler: resolvePipe,
1140
+ priority: TPipePriority.RESOLVE,
1141
+ },
1142
+ ];
1143
+
1144
+ function getOtelMate() {
1145
+ return getMoostMate();
1146
+ }
1147
+
1148
+ const mate = getOtelMate();
1149
+ const OtelIgnoreSpan = () => mate.decorate('otelIgnoreSpan', true);
1150
+ const OtelIgnoreMeter = () => mate.decorate('otelIgnoreMeter', true);
1151
+
1152
+ function shouldSpanBeIgnored(span) {
1153
+ return span.attributes['moost.ignore'] === true;
1154
+ }
1155
+
1156
+ class MoostBatchSpanProcessor extends sdkTraceBase.BatchSpanProcessor {
1157
+ onEnd(span) {
1158
+ if (shouldSpanBeIgnored(span)) {
1159
+ return;
1160
+ }
1161
+ super.onEnd(span);
1162
+ }
1163
+ }
1164
+
1165
+ class MoostSimpleSpanProcessor extends sdkTraceBase.SimpleSpanProcessor {
1166
+ onEnd(span) {
1167
+ if (shouldSpanBeIgnored(span)) {
1168
+ return;
1169
+ }
1170
+ super.onEnd(span);
1171
+ }
108
1172
  }
109
1173
 
1174
+ exports.MoostBatchSpanProcessor = MoostBatchSpanProcessor;
1175
+ exports.MoostSimpleSpanProcessor = MoostSimpleSpanProcessor;
1176
+ exports.OtelIgnoreMeter = OtelIgnoreMeter;
1177
+ exports.OtelIgnoreSpan = OtelIgnoreSpan;
1178
+ exports.SpanInjector = SpanInjector;
110
1179
  exports.enableOtelForMoost = enableOtelForMoost;
1180
+ exports.getOtelMate = getOtelMate;
1181
+ exports.shouldSpanBeIgnored = shouldSpanBeIgnored;
111
1182
  exports.useOtelContext = useOtelContext;
112
1183
  exports.useOtelPropagation = useOtelPropagation;
113
1184
  exports.useSpan = useSpan;