@aidra/pmx-io 0.0.0-stage → 9.13.0

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.
Files changed (67) hide show
  1. package/README.md +69 -2
  2. package/bin/pmx-io-node.js +143 -0
  3. package/index.d.ts +381 -0
  4. package/index.js +27 -0
  5. package/index.mjs +47 -0
  6. package/lib/actions.js +120 -0
  7. package/lib/activate.js +402 -0
  8. package/lib/application.js +106 -0
  9. package/lib/bun.js +155 -0
  10. package/lib/config.js +67 -0
  11. package/lib/constants.js +17 -0
  12. package/lib/debug.js +48 -0
  13. package/lib/esm-hooks.mjs +111 -0
  14. package/lib/exit.js +79 -0
  15. package/lib/features/metrics.js +409 -0
  16. package/lib/features/notify.js +358 -0
  17. package/lib/features/profiling.js +208 -0
  18. package/lib/hooks.js +151 -0
  19. package/lib/inbound.js +174 -0
  20. package/lib/integrations.js +372 -0
  21. package/lib/itg/amqplib.js +169 -0
  22. package/lib/itg/bullmq.js +141 -0
  23. package/lib/itg/common.js +657 -0
  24. package/lib/itg/dbcomment.js +114 -0
  25. package/lib/itg/index.js +103 -0
  26. package/lib/itg/ioredis.js +212 -0
  27. package/lib/itg/kafkajs.js +205 -0
  28. package/lib/itg/mongodb.js +322 -0
  29. package/lib/itg/mysql2.js +205 -0
  30. package/lib/itg/nats.js +531 -0
  31. package/lib/itg/noderedis.js +236 -0
  32. package/lib/itg/pg.js +253 -0
  33. package/lib/itg/pgqueue.js +305 -0
  34. package/lib/itg/postgres.js +252 -0
  35. package/lib/itg/redis-common.js +265 -0
  36. package/lib/itg/sql.js +302 -0
  37. package/lib/metrics/service.js +286 -0
  38. package/lib/metrics/types.js +342 -0
  39. package/lib/modules.js +260 -0
  40. package/lib/node-options.js +62 -0
  41. package/lib/otel/bridge.js +797 -0
  42. package/lib/otel/env.js +114 -0
  43. package/lib/outbound.js +362 -0
  44. package/lib/pmx.js +757 -0
  45. package/lib/relay/hub.js +279 -0
  46. package/lib/relay/transport.js +253 -0
  47. package/lib/standalone/activate.js +307 -0
  48. package/lib/standalone/capture.js +55 -0
  49. package/lib/standalone/container.js +909 -0
  50. package/lib/standalone/transport.js +1023 -0
  51. package/lib/tracing/context.js +90 -0
  52. package/lib/tracing/control.js +124 -0
  53. package/lib/tracing/exporter.js +115 -0
  54. package/lib/tracing/index.js +242 -0
  55. package/lib/tracing/logs.js +176 -0
  56. package/lib/tracing/options.js +105 -0
  57. package/lib/tracing/paths.js +34 -0
  58. package/lib/tracing/tracer.js +850 -0
  59. package/lib/tracing/w3c.js +415 -0
  60. package/lib/transport/ipc.js +97 -0
  61. package/lib/transport/ws.js +511 -0
  62. package/lib/util.js +109 -0
  63. package/package.json +48 -4
  64. package/preload.cjs +26 -0
  65. package/preload.mjs +25 -0
  66. package/standalone.cjs +16 -0
  67. package/standalone.mjs +17 -0
@@ -0,0 +1,531 @@
1
+ // Copyright (c) 2026 Mike Warriner. All rights reserved. Proprietary — see LICENSE.
2
+ 'use strict'
3
+
4
+ // NATS and JetStream (82 §9 ITG-202, ITG-203; common rules §4) for `nats` 2.x and the 3.x modular
5
+ // packages (`@nats-io/nats-core`, `@nats-io/jetstream`, through `@nats-io/transport-node`).
6
+ // * NatsConnectionImpl.publish → PRODUCER `publish <subject>`, trace headers in a copy of
7
+ // `options.headers` (a new headers object from the library's own `headers()` factory);
8
+ // request → CLIENT `request <subject>` until the reply (or the timeout, ERROR); requestMany →
9
+ // CLIENT span until the returned iterator is obtained.
10
+ // * subscribe(subject, { callback }) → callback style; a subscription iterated with `for await`
11
+ // → iterator style (QueuedIteratorImpl's async iterator, for subscriptions marked here).
12
+ // * JetStream: JetStreamClientImpl.publish → PRODUCER covering the ack (`messaging.message.id` =
13
+ // the ack's `seq`, `messaging.nats.stream`); consumers' `consume()` → iterator style, or
14
+ // callback style with `consume({ callback })`;
15
+ // `fetch()` → batch pull (`receive <subject>` from the call until the fetch iterator ends,
16
+ // one link per message); `next()` → batch pull of one.
17
+ // Subjects of the protocol itself (`$JS.`, `$KV.`, `$O.`, `$SYS.`, `_INBOX.`: JetStream API calls,
18
+ // acknowledgements, flow control, replies) make no span, like pmx-io.
19
+
20
+ const path = require('path')
21
+ const c = require('./common')
22
+ const ctx = require('../tracing/context')
23
+
24
+ const SYSTEM = 'nats'
25
+ const META = Symbol('pmx-nats-iter')
26
+ const factories = new Map() // package dir → headers()
27
+
28
+ function internal (subject) {
29
+ return typeof subject !== 'string' || /^(\$JS\.|\$KV\.|\$O\.|\$SYS\.|_INBOX\.)/.test(subject)
30
+ }
31
+
32
+ function peer (nc) {
33
+ const tags = {}
34
+ try {
35
+ const s = typeof nc.getServer === 'function' ? nc.getServer() : ''
36
+ if (s) {
37
+ const i = s.lastIndexOf(':')
38
+ if (i > 0) {
39
+ tags['net.peer.name'] = s.slice(0, i).replace(/^\[|\]$/g, '')
40
+ tags['net.peer.port'] = s.slice(i + 1)
41
+ } else tags['net.peer.name'] = s
42
+ }
43
+ } catch (_) {}
44
+ return tags
45
+ }
46
+
47
+ function hdrsObject (h) {
48
+ if (!h) return null
49
+ const o = {}
50
+ try {
51
+ if (typeof h[Symbol.iterator] === 'function') {
52
+ for (const [k, v] of h) o[String(k).toLowerCase()] = Array.isArray(v) ? v[0] : v
53
+ return o
54
+ }
55
+ if (typeof h.keys === 'function' && typeof h.get === 'function') {
56
+ for (const k of h.keys()) o[String(k).toLowerCase()] = h.get(k)
57
+ return o
58
+ }
59
+ } catch (_) {}
60
+ return null
61
+ }
62
+
63
+ function extractMsg (msg) {
64
+ try {
65
+ const o = hdrsObject(msg && msg.headers)
66
+ return o ? c.extract(o) : null
67
+ } catch (_) {
68
+ return null
69
+ }
70
+ }
71
+
72
+ function supportsHeaders (nc) {
73
+ try {
74
+ const info = nc && nc.info
75
+ return !(info && info.headers === false)
76
+ } catch (_) {
77
+ return true
78
+ }
79
+ }
80
+
81
+ /** A copy of `options` whose `headers` (a new headers object) carries the trace headers. */
82
+ function withTrace (options, span, factory, nc) {
83
+ if (!span) return options
84
+ if (!factory || !supportsHeaders(nc)) {
85
+ span.setAttribute('messaging.pmx.propagation', 'unsupported')
86
+ return options
87
+ }
88
+ const out = Object.assign({}, options || {})
89
+ const h = factory()
90
+ const present = new Set()
91
+ const src = out.headers
92
+ try {
93
+ if (src && typeof src[Symbol.iterator] === 'function') {
94
+ for (const [k, vs] of src) {
95
+ present.add(String(k).toLowerCase())
96
+ for (const v of (Array.isArray(vs) ? vs : [vs])) h.append(k, v)
97
+ }
98
+ }
99
+ } catch (_) {}
100
+ for (const [k, v] of c.traceHeaders(span)) if (!present.has(k)) h.append(k, v)
101
+ out.headers = h
102
+ return out
103
+ }
104
+
105
+ function bodySize (data) {
106
+ return c.bodySize(data)
107
+ }
108
+
109
+ // -- core connection --------------------------------------------------------------------------
110
+
111
+ function wrapPublish (factory) {
112
+ return (orig) => function publish (subject, data, options) {
113
+ if (!c.msgTracer() || internal(subject) || c.nested() || nestedHere()) return orig.apply(this, arguments)
114
+ const tags = Object.assign({}, peer(this))
115
+ const size = bodySize(data)
116
+ if (size !== undefined) tags['messaging.message.body.size'] = String(size)
117
+ const span = c.producer(SYSTEM, subject, tags)
118
+ if (!span) return orig.apply(this, arguments)
119
+ let opts = options
120
+ try {
121
+ opts = withTrace(options, span, factory, this)
122
+ } catch (_) {}
123
+ try {
124
+ const r = c.outer(orig, this, [subject, data, opts])
125
+ c.end(span)
126
+ return r
127
+ } catch (err) {
128
+ c.end(span, err)
129
+ throw err
130
+ }
131
+ }
132
+ }
133
+
134
+ function wrapRequest (factory, many) {
135
+ return (orig) => function request (subject, data, opts) {
136
+ if (!c.msgTracer() || internal(subject) || c.nested() || nestedHere()) return orig.apply(this, arguments)
137
+ const tags = Object.assign({}, peer(this))
138
+ const size = bodySize(data)
139
+ if (size !== undefined) tags['messaging.message.body.size'] = String(size)
140
+ const span = c.producer(SYSTEM, subject, tags, 'CLIENT', 'request')
141
+ if (!span) return orig.apply(this, arguments)
142
+ const args = Array.prototype.slice.call(arguments)
143
+ try {
144
+ args[2] = withTrace(opts, span, factory, this)
145
+ if (args.length < 3) args.length = 3
146
+ } catch (_) {}
147
+ let p
148
+ try {
149
+ p = c.outer(orig, this, args)
150
+ } catch (err) {
151
+ c.end(span, err)
152
+ throw err
153
+ }
154
+ if (c.isThenable(p)) return c.settle(p, span)
155
+ c.end(span)
156
+ return p
157
+ }
158
+ }
159
+
160
+ function wrapSubscribe (orig) {
161
+ return function subscribe (subject, opts) {
162
+ if (!c.msgTracer() || internal(subject)) return orig.apply(this, arguments)
163
+ const nc = this
164
+ const o = opts && typeof opts === 'object' ? opts : {}
165
+ const group = typeof o.queue === 'string' && o.queue ? o.queue : undefined
166
+ if (typeof o.callback === 'function') {
167
+ const cb = o.callback
168
+ const copy = Object.assign({}, o, {
169
+ callback: function (err, msg) {
170
+ if (err || !msg || !c.msgTracer()) return cb.apply(this, arguments)
171
+ const span = consumerSpan(nc, msg, group)
172
+ return c.runConsumer(span, cb, this, arguments)
173
+ }
174
+ })
175
+ return orig.call(this, subject, copy)
176
+ }
177
+ const sub = orig.apply(this, arguments)
178
+ mark(sub, { mode: 'iterator', nc, group })
179
+ return sub
180
+ }
181
+ }
182
+
183
+ function consumerSpan (nc, msg, group, extra) {
184
+ const tags = Object.assign({}, peer(nc), extra || {})
185
+ if (group) tags['messaging.consumer.group.name'] = group
186
+ const size = bodySize(msg && msg.data)
187
+ if (size !== undefined) tags['messaging.message.body.size'] = String(size)
188
+ return c.consumer(SYSTEM, msg && msg.subject, extractMsg(msg), tags)
189
+ }
190
+
191
+ // -- JetStream --------------------------------------------------------------------------------
192
+
193
+ // JetStream publish runs nc.request asynchronously: a store flag suppresses that inner span
194
+ function nestedHere () {
195
+ const s = ctx.current()
196
+ return Boolean(s && s.itg === SYSTEM)
197
+ }
198
+
199
+ function wrapJsPublish (factory) {
200
+ return (orig) => function publish (subject, data, opts) {
201
+ if (!c.msgTracer() || internal(subject) || c.nested() || nestedHere()) return orig.apply(this, arguments)
202
+ const nc = this.nc
203
+ const tags = Object.assign({}, nc ? peer(nc) : {})
204
+ const size = bodySize(data)
205
+ if (size !== undefined) tags['messaging.message.body.size'] = String(size)
206
+ const span = c.producer(SYSTEM, subject, tags)
207
+ if (!span) return orig.apply(this, arguments)
208
+ const args = Array.prototype.slice.call(arguments)
209
+ try {
210
+ args[2] = withTrace(opts, span, factory, nc)
211
+ if (args.length < 3) args.length = 3
212
+ } catch (_) {}
213
+ let p
214
+ try {
215
+ const store = ctx.current()
216
+ p = ctx.run({ span, bag: span.bag, server: store && store.server, itg: SYSTEM }, orig, this, args)
217
+ } catch (err) {
218
+ c.end(span, err)
219
+ throw err
220
+ }
221
+ if (!c.isThenable(p)) {
222
+ c.end(span)
223
+ return p
224
+ }
225
+ return c.settle(p, span, (ack) => {
226
+ if (ack && ack.seq !== undefined) span.setAttribute('messaging.message.id', String(ack.seq))
227
+ if (ack && ack.stream) span.setAttribute('messaging.nats.stream', String(ack.stream))
228
+ })
229
+ }
230
+ }
231
+
232
+ function consumerName (consumer) {
233
+ try {
234
+ return consumer.name || (consumer._info && consumer._info.name) || undefined
235
+ } catch (_) {
236
+ return undefined
237
+ }
238
+ }
239
+
240
+ function jsTags (msg) {
241
+ const tags = {}
242
+ try {
243
+ const info = msg && msg.info
244
+ if (info && info.stream) tags['messaging.nats.stream'] = String(info.stream)
245
+ if (msg && msg.seq !== undefined) tags['messaging.message.id'] = String(msg.seq)
246
+ } catch (_) {}
247
+ return tags
248
+ }
249
+
250
+ // nats 2.x ordered consumers deliver through an internal callback given to an inner consume():
251
+ // those callbacks are marked and not traced (the app's callback or iterator is)
252
+ const INTERNAL = Symbol('pmx-nats-internal')
253
+
254
+ function wrapInternalHandler (orig) {
255
+ return function internalHandler () {
256
+ const fn = orig.apply(this, arguments)
257
+ if (typeof fn === 'function') {
258
+ try {
259
+ Object.defineProperty(fn, INTERNAL, { value: true })
260
+ } catch (_) {}
261
+ }
262
+ return fn
263
+ }
264
+ }
265
+
266
+ /** consume({ callback }): callback style, one CONSUMER span per message (ITG-023). */
267
+ function tracedCallback (cb, meta) {
268
+ const w = function (m) {
269
+ if (!m || !c.msgTracer()) return cb.apply(this, arguments)
270
+ const span = consumerSpan(meta.nc, m, meta.group, jsTags(m))
271
+ return c.runConsumer(span, cb, this, arguments)
272
+ }
273
+ return c.copyMeta(w, cb)
274
+ }
275
+
276
+ function wrapConsume (orig) {
277
+ return function consume (opts) {
278
+ if (c.msgTracer() && opts && typeof opts === 'object' && typeof opts.callback === 'function' && !opts.callback[INTERNAL]) {
279
+ const meta = { nc: this.api && this.api.nc, group: consumerName(this) }
280
+ const args = Array.prototype.slice.call(arguments)
281
+ args[0] = Object.assign({}, opts, { callback: tracedCallback(opts.callback, meta) })
282
+ return orig.apply(this, args)
283
+ }
284
+ const p = orig.apply(this, arguments)
285
+ if (!c.msgTracer()) return p
286
+ const meta = { mode: 'iterator', nc: this.api && this.api.nc, group: consumerName(this), js: true }
287
+ if (c.isThenable(p)) return p.then((it) => { mark(it, meta); return it })
288
+ mark(p, meta)
289
+ return p
290
+ }
291
+ }
292
+
293
+ function wrapFetch (orig) {
294
+ return function fetch () {
295
+ if (!c.msgTracer() || c.nested()) return orig.apply(this, arguments)
296
+ const meta = { mode: 'fetch', nc: this.api && this.api.nc, group: consumerName(this), js: true }
297
+ const tags = Object.assign({}, meta.nc ? peer(meta.nc) : {})
298
+ if (meta.group) tags['messaging.consumer.group.name'] = meta.group
299
+ // created at the call (parent: the current span), kept only when messages came back
300
+ meta.span = c.batchConsumer(SYSTEM, undefined, null, tags, 'receive')
301
+ const p = orig.apply(this, arguments)
302
+ if (c.isThenable(p)) return p.then((it) => { mark(it, meta); return it })
303
+ mark(p, meta)
304
+ return p
305
+ }
306
+ }
307
+
308
+ function wrapNext (orig) {
309
+ return function next () {
310
+ if (!c.msgTracer()) return orig.apply(this, arguments)
311
+ const nc = this.api && this.api.nc
312
+ const group = consumerName(this)
313
+ const tags = Object.assign({}, nc ? peer(nc) : {})
314
+ if (group) tags['messaging.consumer.group.name'] = group
315
+ // created now (covers the call), kept only when a message came back (ITG-023)
316
+ const span = c.batchConsumer(SYSTEM, undefined, null, tags, 'receive')
317
+ let p
318
+ try {
319
+ // 3.x implements next() with fetch(): that inner call makes no span of its own
320
+ p = c.outer(orig, this, arguments)
321
+ } catch (err) {
322
+ c.end(span, err)
323
+ throw err
324
+ }
325
+ if (!span || !c.isThenable(p)) return p
326
+ return p.then((msg) => {
327
+ if (msg) {
328
+ try {
329
+ if (msg.subject) {
330
+ span.setAttribute('messaging.destination.name', msg.subject)
331
+ span.updateName('receive ' + msg.subject)
332
+ }
333
+ Object.entries(jsTags(msg)).forEach(([k, v]) => span.setAttribute(k, v))
334
+ c.addLink(span, extractMsg(msg))
335
+ } catch (_) {}
336
+ c.end(span)
337
+ }
338
+ return msg
339
+ }, (err) => {
340
+ c.end(span, err)
341
+ throw err
342
+ })
343
+ }
344
+ }
345
+
346
+ // -- iterators (subscriptions, consume(), fetch()) --------------------------------------------
347
+
348
+ function mark (it, meta) {
349
+ if (!it || typeof it !== 'object') return
350
+ try {
351
+ Object.defineProperty(it, META, { value: meta, configurable: true })
352
+ } catch (_) {}
353
+ }
354
+
355
+ function wrapAsyncIterator (orig) {
356
+ return function asyncIterator () {
357
+ const it = orig.apply(this, arguments)
358
+ const meta = this && this[META]
359
+ if (!meta || !it || typeof it.next !== 'function' || !c.msgTracer()) return it
360
+ return meta.mode === 'fetch' ? fetchIterator(it, meta) : traceIterator(it, meta)
361
+ }
362
+ }
363
+
364
+ /** Iterator style (ITG-023): one CONSUMER span per message, current for the loop body. */
365
+ function traceIterator (it, meta) {
366
+ const st = c.iterState({})
367
+ const out = {
368
+ next () {
369
+ st.nextRequested()
370
+ let p
371
+ try {
372
+ p = it.next.apply(it, arguments)
373
+ } catch (err) {
374
+ st.closed(true)
375
+ throw err
376
+ }
377
+ return Promise.resolve(p).then((r) => {
378
+ if (r && r.done) st.closed(true)
379
+ else if (r && r.value) {
380
+ try {
381
+ st.delivered(consumerSpan(meta.nc, r.value, meta.group, meta.js ? jsTags(r.value) : undefined))
382
+ } catch (_) {}
383
+ }
384
+ return r
385
+ }, (err) => {
386
+ // the library call itself failed: the open span (if any) is closed by closed()
387
+ st.closed(true)
388
+ throw err
389
+ })
390
+ },
391
+ return () {
392
+ st.closed(true)
393
+ return typeof it.return === 'function' ? it.return.apply(it, arguments) : Promise.resolve({ done: true, value: undefined })
394
+ },
395
+ throw () {
396
+ st.closed(true)
397
+ return typeof it.throw === 'function' ? it.throw.apply(it, arguments) : Promise.reject(arguments[0])
398
+ },
399
+ [Symbol.asyncIterator] () {
400
+ return this
401
+ }
402
+ }
403
+ return out
404
+ }
405
+
406
+ /** Batch pull over an iterator (`fetch()`): a `receive` span from the call to the end, with links. */
407
+ function fetchIterator (it, meta) {
408
+ const span = meta.span
409
+ const subjects = new Set()
410
+ let count = 0
411
+ let finished = false
412
+ const finish = (err) => {
413
+ if (finished || !span) return
414
+ finished = true
415
+ if (err) return c.end(span, err)
416
+ if (count === 0) return
417
+ try {
418
+ if (subjects.size === 1) {
419
+ const s = Array.from(subjects)[0]
420
+ span.setAttribute('messaging.destination.name', s)
421
+ span.updateName('receive ' + s)
422
+ }
423
+ if (count >= 2) span.setAttribute('messaging.batch.message_count', String(count))
424
+ } catch (_) {}
425
+ c.end(span)
426
+ }
427
+ return {
428
+ next () {
429
+ return Promise.resolve(it.next.apply(it, arguments)).then((r) => {
430
+ if (r && r.done) finish()
431
+ else if (r && r.value) {
432
+ count++
433
+ try {
434
+ if (r.value.subject) subjects.add(r.value.subject)
435
+ c.addLink(span, extractMsg(r.value))
436
+ } catch (_) {}
437
+ }
438
+ return r
439
+ }, (err) => {
440
+ finish(err)
441
+ throw err
442
+ })
443
+ },
444
+ return () {
445
+ finish()
446
+ return typeof it.return === 'function' ? it.return.apply(it, arguments) : Promise.resolve({ done: true, value: undefined })
447
+ },
448
+ throw () {
449
+ finish()
450
+ return typeof it.throw === 'function' ? it.throw.apply(it, arguments) : Promise.reject(arguments[0])
451
+ },
452
+ [Symbol.asyncIterator] () {
453
+ return this
454
+ }
455
+ }
456
+ }
457
+
458
+ // -- patches ----------------------------------------------------------------------------------
459
+
460
+ function headersFactory (dir) {
461
+ if (factories.has(dir)) return factories.get(dir)
462
+ let f = null
463
+ for (const rel of ['lib/nats-base-client/headers.js', 'lib/headers.js']) {
464
+ try {
465
+ const m = require(path.join(dir, rel))
466
+ if (typeof m.headers === 'function') {
467
+ f = m.headers
468
+ break
469
+ }
470
+ } catch (_) {}
471
+ }
472
+ factories.set(dir, f)
473
+ return f
474
+ }
475
+
476
+ /** nats/lib/nats-base-client/nats.js (2.x) and @nats-io/nats-core/lib/nats.js (3.x). */
477
+ function patchConnection (exports, info) {
478
+ const Impl = exports && exports.NatsConnectionImpl
479
+ const proto = Impl && Impl.prototype
480
+ if (!proto || typeof proto.publish !== 'function') {
481
+ c.disabled(info.pkg, 'NatsConnectionImpl.publish not found')
482
+ return
483
+ }
484
+ const factory = headersFactory(info.dir)
485
+ c.wrap(proto, 'publish', wrapPublish(factory))
486
+ if (typeof proto.request === 'function') c.wrap(proto, 'request', wrapRequest(factory, false))
487
+ if (typeof proto.requestMany === 'function') c.wrap(proto, 'requestMany', wrapRequest(factory, true))
488
+ if (typeof proto.subscribe === 'function') c.wrap(proto, 'subscribe', wrapSubscribe)
489
+ }
490
+
491
+ /** queued_iterator.js: QueuedIteratorImpl.prototype[Symbol.asyncIterator]. */
492
+ function patchIterator (exports) {
493
+ const Q = exports && exports.QueuedIteratorImpl
494
+ const proto = Q && Q.prototype
495
+ if (!proto || typeof proto[Symbol.asyncIterator] !== 'function') return
496
+ c.wrap(proto, Symbol.asyncIterator, wrapAsyncIterator)
497
+ }
498
+
499
+ /** nats/lib/jetstream/jsclient.js and @nats-io/jetstream/lib/jsclient.js. */
500
+ function patchJsClient (exports, info) {
501
+ const Impl = exports && exports.JetStreamClientImpl
502
+ const proto = Impl && Impl.prototype
503
+ if (!proto || typeof proto.publish !== 'function') {
504
+ c.disabled(info.pkg, 'JetStreamClientImpl.publish not found')
505
+ return
506
+ }
507
+ // the headers factory lives in the core package: nats (same package) or @nats-io/nats-core
508
+ let factory = headersFactory(info.dir)
509
+ if (!factory) {
510
+ try {
511
+ const core = require.resolve('@nats-io/nats-core', { paths: [info.dir] })
512
+ factory = headersFactory(path.dirname(path.dirname(core)))
513
+ } catch (_) {}
514
+ }
515
+ c.wrap(proto, 'publish', wrapJsPublish(factory))
516
+ }
517
+
518
+ /** jetstream consumer.js: PullConsumerImpl / OrderedPullConsumerImpl consume, fetch, next. */
519
+ function patchConsumer (exports) {
520
+ for (const name of ['PullConsumerImpl', 'OrderedPullConsumerImpl']) {
521
+ const K = exports && exports[name]
522
+ const proto = K && K.prototype
523
+ if (!proto) continue
524
+ if (typeof proto.consume === 'function') c.wrap(proto, 'consume', wrapConsume)
525
+ if (typeof proto.internalHandler === 'function') c.wrap(proto, 'internalHandler', wrapInternalHandler)
526
+ if (typeof proto.fetch === 'function') c.wrap(proto, 'fetch', wrapFetch)
527
+ if (typeof proto.next === 'function') c.wrap(proto, 'next', wrapNext)
528
+ }
529
+ }
530
+
531
+ module.exports = { patchConnection, patchIterator, patchJsClient, patchConsumer }