@kultify/kmicro-js 0.1.3 → 0.2.2
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 +135 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -2
- package/dist/index.d.ts +19 -2
- package/dist/index.js +137 -1
- package/dist/index.js.map +1 -1
- package/package.json +19 -18
package/dist/index.cjs
CHANGED
|
@@ -39,6 +39,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
39
39
|
|
|
40
40
|
// src/KMicro.ts
|
|
41
41
|
var import_node_assert = __toESM(require("assert"), 1);
|
|
42
|
+
var import_jetstream = require("@nats-io/jetstream");
|
|
42
43
|
var import_services = require("@nats-io/services");
|
|
43
44
|
var import_transport_node = require("@nats-io/transport-node");
|
|
44
45
|
var import_api = require("@opentelemetry/api");
|
|
@@ -57,14 +58,20 @@ async function init(nats, serviceName, version, description, logger) {
|
|
|
57
58
|
return kmicro;
|
|
58
59
|
}
|
|
59
60
|
var Kmicro = class {
|
|
60
|
-
constructor(meta, logger) {
|
|
61
|
+
constructor(meta, logger, options) {
|
|
61
62
|
this.meta = meta;
|
|
62
63
|
this.logger = logger ?? import_pino.default.pino();
|
|
64
|
+
if (options?.eventSubjectPrefix) {
|
|
65
|
+
this.eventSubjectPrefix = options.eventSubjectPrefix;
|
|
66
|
+
}
|
|
63
67
|
}
|
|
64
68
|
service;
|
|
65
69
|
group;
|
|
66
70
|
nc;
|
|
71
|
+
js;
|
|
72
|
+
consumers = [];
|
|
67
73
|
logger;
|
|
74
|
+
eventSubjectPrefix = "events";
|
|
68
75
|
getLogger(module2) {
|
|
69
76
|
return this.logger.child({ module: module2 });
|
|
70
77
|
}
|
|
@@ -88,7 +95,134 @@ var Kmicro = class {
|
|
|
88
95
|
});
|
|
89
96
|
this.group = this.service.addGroup(this.meta.name);
|
|
90
97
|
}
|
|
98
|
+
getJetStream() {
|
|
99
|
+
(0, import_node_assert.default)(this.nc);
|
|
100
|
+
if (!this.js) {
|
|
101
|
+
this.js = (0, import_jetstream.jetstream)(this.nc);
|
|
102
|
+
}
|
|
103
|
+
return this.js;
|
|
104
|
+
}
|
|
105
|
+
async publish(event) {
|
|
106
|
+
(0, import_node_assert.default)(this.nc);
|
|
107
|
+
const js = this.getJetStream();
|
|
108
|
+
const subject = `${this.eventSubjectPrefix}.${event.orgId}.${event.domain}`;
|
|
109
|
+
const tracer = import_api.trace.getTracer(this.meta.name, this.meta.version);
|
|
110
|
+
await tracer.startActiveSpan(
|
|
111
|
+
`publish: ${subject}`,
|
|
112
|
+
{ kind: import_api.SpanKind.PRODUCER },
|
|
113
|
+
async (span) => {
|
|
114
|
+
try {
|
|
115
|
+
const body = JSON.stringify({
|
|
116
|
+
id: event.id,
|
|
117
|
+
domain: event.domain,
|
|
118
|
+
type: event.type,
|
|
119
|
+
orgId: event.orgId,
|
|
120
|
+
payload: Array.from(event.payload)
|
|
121
|
+
});
|
|
122
|
+
await js.publish(subject, Buffer.from(body), {
|
|
123
|
+
msgID: event.id
|
|
124
|
+
});
|
|
125
|
+
span.setStatus({ code: import_api.SpanStatusCode.OK });
|
|
126
|
+
} catch (error_) {
|
|
127
|
+
span.recordException(error_);
|
|
128
|
+
span.setStatus({ code: import_api.SpanStatusCode.ERROR });
|
|
129
|
+
throw error_;
|
|
130
|
+
} finally {
|
|
131
|
+
span.end();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
async subscribe(streamName, consumerName, handler) {
|
|
137
|
+
const js = this.getJetStream();
|
|
138
|
+
const consumer = await js.consumers.get(streamName, consumerName);
|
|
139
|
+
const messages = await consumer.consume();
|
|
140
|
+
this.consumers.push(messages);
|
|
141
|
+
(async () => {
|
|
142
|
+
for await (const msg of messages) {
|
|
143
|
+
const tracer = import_api.trace.getTracer(this.meta.name, this.meta.version);
|
|
144
|
+
const contextWithOtel = import_api.propagation.extract(
|
|
145
|
+
import_api.context.active(),
|
|
146
|
+
msg.headers,
|
|
147
|
+
{
|
|
148
|
+
get(carrier, key) {
|
|
149
|
+
return carrier?.get(key);
|
|
150
|
+
},
|
|
151
|
+
keys(carrier) {
|
|
152
|
+
return carrier?.keys() ?? [];
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
);
|
|
156
|
+
await tracer.startActiveSpan(
|
|
157
|
+
`event: ${streamName}.${consumerName}`,
|
|
158
|
+
{ kind: import_api.SpanKind.CONSUMER },
|
|
159
|
+
contextWithOtel,
|
|
160
|
+
async (span) => {
|
|
161
|
+
try {
|
|
162
|
+
let event;
|
|
163
|
+
try {
|
|
164
|
+
const parsed = JSON.parse(Buffer.from(msg.data).toString());
|
|
165
|
+
event = {
|
|
166
|
+
id: parsed.id,
|
|
167
|
+
domain: parsed.domain,
|
|
168
|
+
type: parsed.type,
|
|
169
|
+
orgId: parsed.orgId,
|
|
170
|
+
entityId: parsed.entityId,
|
|
171
|
+
payload: new Uint8Array(parsed.payload)
|
|
172
|
+
};
|
|
173
|
+
} catch {
|
|
174
|
+
this.logger.error(
|
|
175
|
+
"failed to unmarshal domain event, terminating message"
|
|
176
|
+
);
|
|
177
|
+
msg.term();
|
|
178
|
+
span.setStatus({ code: import_api.SpanStatusCode.ERROR });
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const header = {};
|
|
182
|
+
for (const key of msg.headers?.keys() ?? []) {
|
|
183
|
+
if (msg.headers?.has(key)) {
|
|
184
|
+
header[key] = msg.headers?.get(key);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const spanLogger = this.logger.child({
|
|
188
|
+
event: `${event.domain}.${event.type}`,
|
|
189
|
+
spanId: span.spanContext().spanId,
|
|
190
|
+
traceId: span.spanContext().traceId
|
|
191
|
+
});
|
|
192
|
+
const requestContext = new RequestContext(
|
|
193
|
+
contextWithOtel,
|
|
194
|
+
span,
|
|
195
|
+
this.getNc(),
|
|
196
|
+
spanLogger,
|
|
197
|
+
{
|
|
198
|
+
callDepth: 0,
|
|
199
|
+
currentService: this.meta.name,
|
|
200
|
+
header
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
await handler(requestContext, event);
|
|
204
|
+
msg.ack();
|
|
205
|
+
span.setStatus({ code: import_api.SpanStatusCode.OK });
|
|
206
|
+
} catch (error_) {
|
|
207
|
+
this.logger.error(
|
|
208
|
+
{ err: error_ },
|
|
209
|
+
`error in event handler: ${error_?.message}`
|
|
210
|
+
);
|
|
211
|
+
span.recordException(error_);
|
|
212
|
+
span.setStatus({ code: import_api.SpanStatusCode.ERROR });
|
|
213
|
+
msg.nak();
|
|
214
|
+
} finally {
|
|
215
|
+
span.end();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
})();
|
|
221
|
+
}
|
|
91
222
|
async stop() {
|
|
223
|
+
for (const consumer of this.consumers) {
|
|
224
|
+
consumer.close();
|
|
225
|
+
}
|
|
92
226
|
await this.service?.stop().catch((error) => {
|
|
93
227
|
console.error(error);
|
|
94
228
|
});
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/KMicro.ts"],"sourcesContent":["export * from \"./KMicro.js\";\n","import assert from \"node:assert\";\nimport { type Service, type ServiceGroup, Svcm } from \"@nats-io/services\";\nimport { connect, headers, type NatsConnection } from \"@nats-io/transport-node\";\nimport {\n\ttype Context,\n\tcontext,\n\tpropagation,\n\ttype Span,\n\tSpanKind,\n\tSpanStatusCode,\n\ttrace,\n} from \"@opentelemetry/api\";\nimport {\n\tATTR_RPC_METHOD,\n\tATTR_RPC_SERVICE,\n} from \"@opentelemetry/semantic-conventions/incubating\";\nimport pino, { type Logger } from \"pino\";\n\n/**\n * Use init to create a kmicro instance and directly start (init) it\n */\nexport async function init(\n\tnats: string,\n\tserviceName: string,\n\tversion: string,\n\tdescription?: string,\n\tlogger?: Logger,\n) {\n\tconst kmicro = new Kmicro(\n\t\t{\n\t\t\tname: serviceName,\n\t\t\tversion,\n\t\t\tdescription,\n\t\t},\n\t\tlogger,\n\t);\n\tawait kmicro.init(nats);\n\treturn kmicro;\n}\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\ninterface Callable {\n\tcall(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t},\n\t): Promise<Uint8Array>;\n}\n\nexport class Kmicro implements Callable {\n\tprivate service: Service | undefined;\n\tprivate group: ServiceGroup | undefined;\n\tprivate nc: NatsConnection | undefined;\n\tprivate readonly logger: Logger;\n\n\tconstructor(\n\t\tprivate readonly meta: {\n\t\t\tname: string;\n\t\t\tversion: string;\n\t\t\tdescription: string | undefined;\n\t\t},\n\t\tlogger?: Logger,\n\t) {\n\t\tthis.logger = logger ?? pino.pino();\n\t}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.logger.child({ module });\n\t}\n\n\tpublic getNc(): NatsConnection {\n\t\tassert(this.nc);\n\t\treturn this.nc;\n\t}\n\n\tpublic async init(natsURI: string) {\n\t\tconst natsUrl = new URL(natsURI);\n\t\tthis.nc = await connect({\n\t\t\tname: this.meta.name,\n\t\t\tuser: natsUrl.username,\n\t\t\tpass: natsUrl.password,\n\t\t\tservers: [natsUrl.host],\n\t\t});\n\t\tconst svc = new Svcm(this.nc);\n\t\tthis.service = await svc.add({\n\t\t\tname: this.meta.name,\n\t\t\tversion: this.meta.version,\n\t\t\tdescription: this.meta.description,\n\t\t});\n\t\tthis.group = this.service.addGroup(this.meta.name);\n\t}\n\n\tpublic async stop() {\n\t\tawait this.service?.stop().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t\tawait this.nc?.close().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t}\n\n\tpublic addEndpoint(\n\t\tname: string,\n\t\thandler: (\n\t\t\tcontext_: RequestContext,\n\t\t\tdata: Uint8Array,\n\t\t) => Promise<Uint8Array>,\n\t) {\n\t\tassert(this.group);\n\n\t\tthis.group.addEndpoint(name, async (error, message) => {\n\t\t\tassert(this.nc);\n\t\t\tif (error) {\n\t\t\t\tconsole.error(error);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Prevent infinite loops\n\t\t\tconst currentCallDepth = Number.parseInt(\n\t\t\t\tmessage.headers?.get(\"kmc-depth\") ?? \"0\",\n\t\t\t\t10,\n\t\t\t);\n\t\t\tif (currentCallDepth >= 20) {\n\t\t\t\tthrow new Error(`max call depth reached: ${currentCallDepth}`);\n\t\t\t}\n\n\t\t\tconst contextWithOtel: Context = propagation.extract(\n\t\t\t\tcontext.active(),\n\t\t\t\tmessage.headers,\n\t\t\t\t{\n\t\t\t\t\tget(carrier, key) {\n\t\t\t\t\t\treturn carrier?.get(key);\n\t\t\t\t\t},\n\t\t\t\t\tkeys(carrier) {\n\t\t\t\t\t\treturn carrier?.keys() ?? [];\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst tracer = trace.getTracer(this.meta.name, this.meta.version);\n\t\t\tconst spanName = `handle: ${this.meta.name}.${name}`;\n\t\t\tawait tracer.startActiveSpan(\n\t\t\t\tspanName,\n\t\t\t\t{\n\t\t\t\t\tkind: SpanKind.SERVER,\n\t\t\t\t},\n\t\t\t\tcontextWithOtel,\n\t\t\t\tasync (span) => {\n\t\t\t\t\tconst spanLogger = this.logger.child({\n\t\t\t\t\t\taction: name,\n\t\t\t\t\t\tspanId: span.spanContext().spanId,\n\t\t\t\t\t\ttraceId: span.spanContext().traceId,\n\t\t\t\t\t});\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst header: Record<string, string> = {};\n\t\t\t\t\t\tfor (const key of message.headers?.keys() ?? []) {\n\t\t\t\t\t\t\tif (message.headers?.has(key)) {\n\t\t\t\t\t\t\t\theader[key] = message.headers?.get(key);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst requestContext = new RequestContext(\n\t\t\t\t\t\t\tcontextWithOtel,\n\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: Checked with assert\n\t\t\t\t\t\t\tthis.nc!,\n\t\t\t\t\t\t\tspanLogger,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcallDepth: currentCallDepth,\n\t\t\t\t\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst result = await handler(requestContext, message.data);\n\t\t\t\t\t\tmessage.respond(result);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t\t} catch (error_) {\n\t\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\terr: error_,\n\t\t\t\t\t\t\t\taction: name,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t`error in handler: ${(error_ as Error)?.message}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tspan.recordException(error_ as Error);\n\t\t\t\t\t\tmessage.respondError(500, (error_ as Error).message);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tspan.end();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Start a new call\n\t */\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t\tmoleculerTrace?: {\n\t\t\t\ttraceId?: string | undefined;\n\t\t\t\tparentId?: string | undefined;\n\t\t\t};\n\t\t},\n\t): Promise<Uint8Array> {\n\t\tassert(this.nc);\n\n\t\tlet trace:\n\t\t\t| undefined\n\t\t\t| {\n\t\t\t\t\ttraceId: string;\n\t\t\t\t\tparentId: string;\n\t\t\t };\n\t\tif (options?.moleculerTrace) {\n\t\t\t// we have to shorten the moleculer trace id because the jaeger exporter uses only 16 chars\n\t\t\tconst molTraceId = options.moleculerTrace.traceId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\tconst traceId = Array.from({ length: 16 })\n\t\t\t\t.fill(\"0\")\n\t\t\t\t.join(\"\")\n\t\t\t\t.concat(molTraceId ?? \"\");\n\t\t\tconst molParentId = options.moleculerTrace.parentId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\ttrace = {\n\t\t\t\ttraceId,\n\t\t\t\tparentId: molParentId ?? \"\",\n\t\t\t};\n\t\t}\n\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: 0,\n\t\t\t\tcontext: undefined,\n\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\theader: options?.header ?? {},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttimeout: options?.timeout,\n\t\t\t\ttrace,\n\t\t\t},\n\t\t);\n\t}\n}\n\nexport class RequestContext {\n\t// eslint-disable-next-line max-params\n\tconstructor(\n\t\treadonly context: Context,\n\t\treadonly span: Span,\n\t\treadonly nc: NatsConnection,\n\t\tprivate readonly logger: Logger,\n\t\treadonly meta: {\n\t\t\tcallDepth: number;\n\t\t\tcurrentService: string;\n\t\t\theader: Record<string, string>;\n\t\t},\n\t) {}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.logger.child({\n\t\t\tmodule,\n\t\t});\n\t}\n\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t},\n\t): Promise<Uint8Array> {\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: this.meta.callDepth,\n\t\t\t\tcontext: this.context,\n\t\t\t\tcurrentService: this.meta.currentService,\n\t\t\t\theader: this.meta.header,\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n}\n\nexport class CallError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tprivate readonly target: string,\n\t\tprivate readonly payload: Uint8Array,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CallError\";\n\t}\n}\n\n// eslint-disable-next-line max-params\nasync function doCall(\n\tnc: NatsConnection,\n\ttarget: string,\n\tpayload: Uint8Array,\n\tmeta: {\n\t\tcallDepth: number;\n\t\t/**\n\t\t * The otel context\n\t\t */\n\t\tcontext: Context | undefined;\n\t\tcurrentService: string;\n\t\t/**\n\t\t * Headers from the parent calls\n\t\t */\n\t\theader: Record<string, string>;\n\t},\n\toptions?: {\n\t\t/**\n\t\t * @default 5000 ms\n\t\t */\n\t\ttimeout?: number;\n\t\theader?: Record<string, string>;\n\t\t/**\n\t\t * Optionally pass an existing trace from the moleculer framework\n\t\t */\n\t\ttrace?: {\n\t\t\t/**\n\t\t\t * This is the ID of the whole trace forest and is used to uniquely identify a distributed trace through a system.\n\t\t\t */\n\t\t\ttraceId: string | undefined;\n\t\t\t/**\n\t\t\t * or span id: This is the ID of this request as known by the caller\n\t\t\t */\n\t\t\tparentId: string | undefined;\n\t\t};\n\t},\n): Promise<Uint8Array> {\n\tif (meta.callDepth >= 20) {\n\t\tthrow new Error(`max call depth reached: ${meta.callDepth}`);\n\t}\n\n\tconst carrierData: Context | { traceparent?: string } = meta.context ?? {};\n\tif (options?.trace && !meta.context) {\n\t\tconst version = Buffer.alloc(1).toString(\"hex\");\n\t\tconst flags = \"01\"; // means sampled\n\t\tconst header = `${version}-${options.trace.traceId}-${options.trace.parentId}-${flags}`;\n\t\t(carrierData as { traceparent?: string | undefined }).traceparent = header;\n\t}\n\n\tconst callingContext: Context = propagation.extract(\n\t\tcontext.active(),\n\t\tcarrierData,\n\t);\n\tconst tracer = trace.getTracer(\"default\");\n\tconst [service, action] = target.split(\".\");\n\treturn tracer.startActiveSpan(\n\t\t`call: ${target}`,\n\t\t{\n\t\t\tkind: SpanKind.CLIENT,\n\t\t\tattributes: {\n\t\t\t\t[ATTR_RPC_SERVICE]: service,\n\t\t\t\t[ATTR_RPC_METHOD]: action,\n\t\t\t},\n\t\t},\n\t\tcallingContext,\n\t\tasync (span) => {\n\t\t\t// Add kmicro and otel headers to the nats message headers\n\t\t\tconst natsHeadersMap = headers();\n\t\t\tnatsHeadersMap.set(\"kmc-depth\", (meta.callDepth + 1).toFixed(0));\n\t\t\tpropagation.inject(context.active(), natsHeadersMap, {\n\t\t\t\tset(carrier, key, value) {\n\t\t\t\t\tcarrier.set(key, value);\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst mergedHeaders = { ...meta.header, ...options?.header };\n\t\t\tfor (const key in mergedHeaders) {\n\t\t\t\tif (!Object.hasOwn(mergedHeaders, key)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (mergedHeaders[key]) {\n\t\t\t\t\tnatsHeadersMap.set(key, mergedHeaders[key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await nc.request(target, payload, {\n\t\t\t\t\theaders: natsHeadersMap,\n\t\t\t\t\ttimeout: options?.timeout ?? 5000,\n\t\t\t\t});\n\t\t\t\tif (result.headers?.get(\"Nats-Service-Error-Code\")) {\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\tspan.recordException(result.headers.get(\"Nats-Service-Error\"));\n\t\t\t\t\tthrow new CallError(\n\t\t\t\t\t\t`received error: ${result.headers.get(\"Nats-Service-Error\")}`,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tpayload,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\treturn result.data;\n\t\t\t} finally {\n\t\t\t\tspan.end();\n\t\t\t}\n\t\t},\n\t);\n}\n"],"mappings":"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","names":["pino","module","assert","trace","context"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/KMicro.ts"],"sourcesContent":["export * from \"./KMicro.js\";\n","import assert from \"node:assert\";\nimport {\n\ttype ConsumerMessages,\n\ttype JetStreamClient,\n\tjetstream,\n} from \"@nats-io/jetstream\";\nimport { type Service, type ServiceGroup, Svcm } from \"@nats-io/services\";\nimport { connect, headers, type NatsConnection } from \"@nats-io/transport-node\";\nimport {\n\ttype Context,\n\tcontext,\n\tpropagation,\n\ttype Span,\n\tSpanKind,\n\tSpanStatusCode,\n\ttrace,\n} from \"@opentelemetry/api\";\nimport {\n\tATTR_RPC_METHOD,\n\tATTR_RPC_SERVICE,\n} from \"@opentelemetry/semantic-conventions/incubating\";\nimport pino, { type Logger } from \"pino\";\n\n/**\n * Use init to create a kmicro instance and directly start (init) it\n */\nexport async function init(\n\tnats: string,\n\tserviceName: string,\n\tversion: string,\n\tdescription?: string,\n\tlogger?: Logger,\n) {\n\tconst kmicro = new Kmicro(\n\t\t{\n\t\t\tname: serviceName,\n\t\t\tversion,\n\t\t\tdescription,\n\t\t},\n\t\tlogger,\n\t);\n\tawait kmicro.init(nats);\n\treturn kmicro;\n}\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\ninterface Callable {\n\tcall(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t},\n\t): Promise<Uint8Array>;\n}\n\nexport type DomainEvent = {\n\tid: string;\n\tdomain: string;\n\ttype: string;\n\torgId: string;\n\tentityId: string;\n\tpayload: Uint8Array;\n};\n\nexport type EventHandler = (\n\tcontext_: RequestContext,\n\tevent: DomainEvent,\n) => Promise<void>;\n\nexport class Kmicro implements Callable {\n\tprivate service: Service | undefined;\n\tprivate group: ServiceGroup | undefined;\n\tprivate nc: NatsConnection | undefined;\n\tprivate js: JetStreamClient | undefined;\n\tprivate readonly consumers: ConsumerMessages[] = [];\n\tprivate readonly logger: Logger;\n\tprivate eventSubjectPrefix = \"events\";\n\n\tconstructor(\n\t\tprivate readonly meta: {\n\t\t\tname: string;\n\t\t\tversion: string;\n\t\t\tdescription: string | undefined;\n\t\t},\n\t\tlogger?: Logger,\n\t\toptions?: {\n\t\t\teventSubjectPrefix?: string;\n\t\t},\n\t) {\n\t\tthis.logger = logger ?? pino.pino();\n\t\tif (options?.eventSubjectPrefix) {\n\t\t\tthis.eventSubjectPrefix = options.eventSubjectPrefix;\n\t\t}\n\t}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.logger.child({ module });\n\t}\n\n\tpublic getNc(): NatsConnection {\n\t\tassert(this.nc);\n\t\treturn this.nc;\n\t}\n\n\tpublic async init(natsURI: string) {\n\t\tconst natsUrl = new URL(natsURI);\n\t\tthis.nc = await connect({\n\t\t\tname: this.meta.name,\n\t\t\tuser: natsUrl.username,\n\t\t\tpass: natsUrl.password,\n\t\t\tservers: [natsUrl.host],\n\t\t});\n\t\tconst svc = new Svcm(this.nc);\n\t\tthis.service = await svc.add({\n\t\t\tname: this.meta.name,\n\t\t\tversion: this.meta.version,\n\t\t\tdescription: this.meta.description,\n\t\t});\n\t\tthis.group = this.service.addGroup(this.meta.name);\n\t}\n\n\tprivate getJetStream(): JetStreamClient {\n\t\tassert(this.nc);\n\t\tif (!this.js) {\n\t\t\tthis.js = jetstream(this.nc);\n\t\t}\n\t\treturn this.js;\n\t}\n\n\tpublic async publish(event: DomainEvent): Promise<void> {\n\t\tassert(this.nc);\n\t\tconst js = this.getJetStream();\n\t\tconst subject = `${this.eventSubjectPrefix}.${event.orgId}.${event.domain}`;\n\n\t\tconst tracer = trace.getTracer(this.meta.name, this.meta.version);\n\t\tawait tracer.startActiveSpan(\n\t\t\t`publish: ${subject}`,\n\t\t\t{ kind: SpanKind.PRODUCER },\n\t\t\tasync (span) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst body = JSON.stringify({\n\t\t\t\t\t\tid: event.id,\n\t\t\t\t\t\tdomain: event.domain,\n\t\t\t\t\t\ttype: event.type,\n\t\t\t\t\t\torgId: event.orgId,\n\t\t\t\t\t\tpayload: Array.from(event.payload),\n\t\t\t\t\t});\n\n\t\t\t\t\tawait js.publish(subject, Buffer.from(body), {\n\t\t\t\t\t\tmsgID: event.id,\n\t\t\t\t\t});\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t} catch (error_) {\n\t\t\t\t\tspan.recordException(error_ as Error);\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\tthrow error_;\n\t\t\t\t} finally {\n\t\t\t\t\tspan.end();\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t}\n\n\tpublic async subscribe(\n\t\tstreamName: string,\n\t\tconsumerName: string,\n\t\thandler: EventHandler,\n\t): Promise<void> {\n\t\tconst js = this.getJetStream();\n\t\tconst consumer = await js.consumers.get(streamName, consumerName);\n\t\tconst messages = await consumer.consume();\n\t\tthis.consumers.push(messages);\n\n\t\t(async () => {\n\t\t\tfor await (const msg of messages) {\n\t\t\t\tconst tracer = trace.getTracer(this.meta.name, this.meta.version);\n\n\t\t\t\tconst contextWithOtel: Context = propagation.extract(\n\t\t\t\t\tcontext.active(),\n\t\t\t\t\tmsg.headers,\n\t\t\t\t\t{\n\t\t\t\t\t\tget(carrier, key) {\n\t\t\t\t\t\t\treturn carrier?.get(key);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tkeys(carrier) {\n\t\t\t\t\t\t\treturn carrier?.keys() ?? [];\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tawait tracer.startActiveSpan(\n\t\t\t\t\t`event: ${streamName}.${consumerName}`,\n\t\t\t\t\t{ kind: SpanKind.CONSUMER },\n\t\t\t\t\tcontextWithOtel,\n\t\t\t\t\tasync (span) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tlet event: DomainEvent;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst parsed = JSON.parse(Buffer.from(msg.data).toString());\n\t\t\t\t\t\t\t\tevent = {\n\t\t\t\t\t\t\t\t\tid: parsed.id,\n\t\t\t\t\t\t\t\t\tdomain: parsed.domain,\n\t\t\t\t\t\t\t\t\ttype: parsed.type,\n\t\t\t\t\t\t\t\t\torgId: parsed.orgId,\n\t\t\t\t\t\t\t\t\tentityId: parsed.entityId,\n\t\t\t\t\t\t\t\t\tpayload: new Uint8Array(parsed.payload),\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t\t\t\t\"failed to unmarshal domain event, terminating message\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tmsg.term();\n\t\t\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst header: Record<string, string> = {};\n\t\t\t\t\t\t\tfor (const key of msg.headers?.keys() ?? []) {\n\t\t\t\t\t\t\t\tif (msg.headers?.has(key)) {\n\t\t\t\t\t\t\t\t\theader[key] = msg.headers?.get(key);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst spanLogger = this.logger.child({\n\t\t\t\t\t\t\t\tevent: `${event.domain}.${event.type}`,\n\t\t\t\t\t\t\t\tspanId: span.spanContext().spanId,\n\t\t\t\t\t\t\t\ttraceId: span.spanContext().traceId,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst requestContext = new RequestContext(\n\t\t\t\t\t\t\t\tcontextWithOtel,\n\t\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t\tthis.getNc(),\n\t\t\t\t\t\t\t\tspanLogger,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcallDepth: 0,\n\t\t\t\t\t\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tawait handler(requestContext, event);\n\t\t\t\t\t\t\tmsg.ack();\n\t\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t\t\t} catch (error_) {\n\t\t\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t\t\t{ err: error_ },\n\t\t\t\t\t\t\t\t`error in event handler: ${(error_ as Error)?.message}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tspan.recordException(error_ as Error);\n\t\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\t\t\tmsg.nak();\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tspan.end();\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t})();\n\t}\n\n\tpublic async stop() {\n\t\tfor (const consumer of this.consumers) {\n\t\t\tconsumer.close();\n\t\t}\n\t\tawait this.service?.stop().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t\tawait this.nc?.close().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t}\n\n\tpublic addEndpoint(\n\t\tname: string,\n\t\thandler: (\n\t\t\tcontext_: RequestContext,\n\t\t\tdata: Uint8Array,\n\t\t) => Promise<Uint8Array>,\n\t) {\n\t\tassert(this.group);\n\n\t\tthis.group.addEndpoint(name, async (error, message) => {\n\t\t\tassert(this.nc);\n\t\t\tif (error) {\n\t\t\t\tconsole.error(error);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Prevent infinite loops\n\t\t\tconst currentCallDepth = Number.parseInt(\n\t\t\t\tmessage.headers?.get(\"kmc-depth\") ?? \"0\",\n\t\t\t\t10,\n\t\t\t);\n\t\t\tif (currentCallDepth >= 20) {\n\t\t\t\tthrow new Error(`max call depth reached: ${currentCallDepth}`);\n\t\t\t}\n\n\t\t\tconst contextWithOtel: Context = propagation.extract(\n\t\t\t\tcontext.active(),\n\t\t\t\tmessage.headers,\n\t\t\t\t{\n\t\t\t\t\tget(carrier, key) {\n\t\t\t\t\t\treturn carrier?.get(key);\n\t\t\t\t\t},\n\t\t\t\t\tkeys(carrier) {\n\t\t\t\t\t\treturn carrier?.keys() ?? [];\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst tracer = trace.getTracer(this.meta.name, this.meta.version);\n\t\t\tconst spanName = `handle: ${this.meta.name}.${name}`;\n\t\t\tawait tracer.startActiveSpan(\n\t\t\t\tspanName,\n\t\t\t\t{\n\t\t\t\t\tkind: SpanKind.SERVER,\n\t\t\t\t},\n\t\t\t\tcontextWithOtel,\n\t\t\t\tasync (span) => {\n\t\t\t\t\tconst spanLogger = this.logger.child({\n\t\t\t\t\t\taction: name,\n\t\t\t\t\t\tspanId: span.spanContext().spanId,\n\t\t\t\t\t\ttraceId: span.spanContext().traceId,\n\t\t\t\t\t});\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst header: Record<string, string> = {};\n\t\t\t\t\t\tfor (const key of message.headers?.keys() ?? []) {\n\t\t\t\t\t\t\tif (message.headers?.has(key)) {\n\t\t\t\t\t\t\t\theader[key] = message.headers?.get(key);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst requestContext = new RequestContext(\n\t\t\t\t\t\t\tcontextWithOtel,\n\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: Checked with assert\n\t\t\t\t\t\t\tthis.nc!,\n\t\t\t\t\t\t\tspanLogger,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcallDepth: currentCallDepth,\n\t\t\t\t\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst result = await handler(requestContext, message.data);\n\t\t\t\t\t\tmessage.respond(result);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t\t} catch (error_) {\n\t\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\terr: error_,\n\t\t\t\t\t\t\t\taction: name,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t`error in handler: ${(error_ as Error)?.message}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tspan.recordException(error_ as Error);\n\t\t\t\t\t\tmessage.respondError(500, (error_ as Error).message);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tspan.end();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Start a new call\n\t */\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t\tmoleculerTrace?: {\n\t\t\t\ttraceId?: string | undefined;\n\t\t\t\tparentId?: string | undefined;\n\t\t\t};\n\t\t},\n\t): Promise<Uint8Array> {\n\t\tassert(this.nc);\n\n\t\tlet trace:\n\t\t\t| undefined\n\t\t\t| {\n\t\t\t\t\ttraceId: string;\n\t\t\t\t\tparentId: string;\n\t\t\t };\n\t\tif (options?.moleculerTrace) {\n\t\t\t// we have to shorten the moleculer trace id because the jaeger exporter uses only 16 chars\n\t\t\tconst molTraceId = options.moleculerTrace.traceId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\tconst traceId = Array.from({ length: 16 })\n\t\t\t\t.fill(\"0\")\n\t\t\t\t.join(\"\")\n\t\t\t\t.concat(molTraceId ?? \"\");\n\t\t\tconst molParentId = options.moleculerTrace.parentId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\ttrace = {\n\t\t\t\ttraceId,\n\t\t\t\tparentId: molParentId ?? \"\",\n\t\t\t};\n\t\t}\n\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: 0,\n\t\t\t\tcontext: undefined,\n\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\theader: options?.header ?? {},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttimeout: options?.timeout,\n\t\t\t\ttrace,\n\t\t\t},\n\t\t);\n\t}\n}\n\nexport class RequestContext {\n\t// eslint-disable-next-line max-params\n\tconstructor(\n\t\treadonly context: Context,\n\t\treadonly span: Span,\n\t\treadonly nc: NatsConnection,\n\t\tprivate readonly logger: Logger,\n\t\treadonly meta: {\n\t\t\tcallDepth: number;\n\t\t\tcurrentService: string;\n\t\t\theader: Record<string, string>;\n\t\t},\n\t) {}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.logger.child({\n\t\t\tmodule,\n\t\t});\n\t}\n\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t},\n\t): Promise<Uint8Array> {\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: this.meta.callDepth,\n\t\t\t\tcontext: this.context,\n\t\t\t\tcurrentService: this.meta.currentService,\n\t\t\t\theader: this.meta.header,\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n}\n\nexport class CallError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tprivate readonly target: string,\n\t\tprivate readonly payload: Uint8Array,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CallError\";\n\t}\n}\n\n// eslint-disable-next-line max-params\nasync function doCall(\n\tnc: NatsConnection,\n\ttarget: string,\n\tpayload: Uint8Array,\n\tmeta: {\n\t\tcallDepth: number;\n\t\t/**\n\t\t * The otel context\n\t\t */\n\t\tcontext: Context | undefined;\n\t\tcurrentService: string;\n\t\t/**\n\t\t * Headers from the parent calls\n\t\t */\n\t\theader: Record<string, string>;\n\t},\n\toptions?: {\n\t\t/**\n\t\t * @default 5000 ms\n\t\t */\n\t\ttimeout?: number;\n\t\theader?: Record<string, string>;\n\t\t/**\n\t\t * Optionally pass an existing trace from the moleculer framework\n\t\t */\n\t\ttrace?: {\n\t\t\t/**\n\t\t\t * This is the ID of the whole trace forest and is used to uniquely identify a distributed trace through a system.\n\t\t\t */\n\t\t\ttraceId: string | undefined;\n\t\t\t/**\n\t\t\t * or span id: This is the ID of this request as known by the caller\n\t\t\t */\n\t\t\tparentId: string | undefined;\n\t\t};\n\t},\n): Promise<Uint8Array> {\n\tif (meta.callDepth >= 20) {\n\t\tthrow new Error(`max call depth reached: ${meta.callDepth}`);\n\t}\n\n\tconst carrierData: Context | { traceparent?: string } = meta.context ?? {};\n\tif (options?.trace && !meta.context) {\n\t\tconst version = Buffer.alloc(1).toString(\"hex\");\n\t\tconst flags = \"01\"; // means sampled\n\t\tconst header = `${version}-${options.trace.traceId}-${options.trace.parentId}-${flags}`;\n\t\t(carrierData as { traceparent?: string | undefined }).traceparent = header;\n\t}\n\n\tconst callingContext: Context = propagation.extract(\n\t\tcontext.active(),\n\t\tcarrierData,\n\t);\n\tconst tracer = trace.getTracer(\"default\");\n\tconst [service, action] = target.split(\".\");\n\treturn tracer.startActiveSpan(\n\t\t`call: ${target}`,\n\t\t{\n\t\t\tkind: SpanKind.CLIENT,\n\t\t\tattributes: {\n\t\t\t\t[ATTR_RPC_SERVICE]: service,\n\t\t\t\t[ATTR_RPC_METHOD]: action,\n\t\t\t},\n\t\t},\n\t\tcallingContext,\n\t\tasync (span) => {\n\t\t\t// Add kmicro and otel headers to the nats message headers\n\t\t\tconst natsHeadersMap = headers();\n\t\t\tnatsHeadersMap.set(\"kmc-depth\", (meta.callDepth + 1).toFixed(0));\n\t\t\tpropagation.inject(context.active(), natsHeadersMap, {\n\t\t\t\tset(carrier, key, value) {\n\t\t\t\t\tcarrier.set(key, value);\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst mergedHeaders = { ...meta.header, ...options?.header };\n\t\t\tfor (const key in mergedHeaders) {\n\t\t\t\tif (!Object.hasOwn(mergedHeaders, key)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (mergedHeaders[key]) {\n\t\t\t\t\tnatsHeadersMap.set(key, mergedHeaders[key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await nc.request(target, payload, {\n\t\t\t\t\theaders: natsHeadersMap,\n\t\t\t\t\ttimeout: options?.timeout ?? 5000,\n\t\t\t\t});\n\t\t\t\tif (result.headers?.get(\"Nats-Service-Error-Code\")) {\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\tspan.recordException(result.headers.get(\"Nats-Service-Error\"));\n\t\t\t\t\tthrow new CallError(\n\t\t\t\t\t\t`received error: ${result.headers.get(\"Nats-Service-Error\")}`,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tpayload,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\treturn result.data;\n\t\t\t} finally {\n\t\t\t\tspan.end();\n\t\t\t}\n\t\t},\n\t);\n}\n"],"mappings":"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","names":["pino","module","assert","trace","context"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -14,20 +14,37 @@ interface Callable {
|
|
|
14
14
|
timeout?: number;
|
|
15
15
|
}): Promise<Uint8Array>;
|
|
16
16
|
}
|
|
17
|
+
type DomainEvent = {
|
|
18
|
+
id: string;
|
|
19
|
+
domain: string;
|
|
20
|
+
type: string;
|
|
21
|
+
orgId: string;
|
|
22
|
+
entityId: string;
|
|
23
|
+
payload: Uint8Array;
|
|
24
|
+
};
|
|
25
|
+
type EventHandler = (context_: RequestContext, event: DomainEvent) => Promise<void>;
|
|
17
26
|
declare class Kmicro implements Callable {
|
|
18
27
|
private readonly meta;
|
|
19
28
|
private service;
|
|
20
29
|
private group;
|
|
21
30
|
private nc;
|
|
31
|
+
private js;
|
|
32
|
+
private readonly consumers;
|
|
22
33
|
private readonly logger;
|
|
34
|
+
private eventSubjectPrefix;
|
|
23
35
|
constructor(meta: {
|
|
24
36
|
name: string;
|
|
25
37
|
version: string;
|
|
26
38
|
description: string | undefined;
|
|
27
|
-
}, logger?: Logger
|
|
39
|
+
}, logger?: Logger, options?: {
|
|
40
|
+
eventSubjectPrefix?: string;
|
|
41
|
+
});
|
|
28
42
|
getLogger(module?: string): pino.Logger<never, boolean>;
|
|
29
43
|
getNc(): NatsConnection;
|
|
30
44
|
init(natsURI: string): Promise<void>;
|
|
45
|
+
private getJetStream;
|
|
46
|
+
publish(event: DomainEvent): Promise<void>;
|
|
47
|
+
subscribe(streamName: string, consumerName: string, handler: EventHandler): Promise<void>;
|
|
31
48
|
stop(): Promise<void>;
|
|
32
49
|
addEndpoint(name: string, handler: (context_: RequestContext, data: Uint8Array) => Promise<Uint8Array>): void;
|
|
33
50
|
/**
|
|
@@ -75,4 +92,4 @@ declare class CallError extends Error {
|
|
|
75
92
|
constructor(message: string, target: string, payload: Uint8Array);
|
|
76
93
|
}
|
|
77
94
|
|
|
78
|
-
export { CallError, Kmicro, RequestContext, init };
|
|
95
|
+
export { CallError, type DomainEvent, type EventHandler, Kmicro, RequestContext, init };
|
package/dist/index.d.ts
CHANGED
|
@@ -14,20 +14,37 @@ interface Callable {
|
|
|
14
14
|
timeout?: number;
|
|
15
15
|
}): Promise<Uint8Array>;
|
|
16
16
|
}
|
|
17
|
+
type DomainEvent = {
|
|
18
|
+
id: string;
|
|
19
|
+
domain: string;
|
|
20
|
+
type: string;
|
|
21
|
+
orgId: string;
|
|
22
|
+
entityId: string;
|
|
23
|
+
payload: Uint8Array;
|
|
24
|
+
};
|
|
25
|
+
type EventHandler = (context_: RequestContext, event: DomainEvent) => Promise<void>;
|
|
17
26
|
declare class Kmicro implements Callable {
|
|
18
27
|
private readonly meta;
|
|
19
28
|
private service;
|
|
20
29
|
private group;
|
|
21
30
|
private nc;
|
|
31
|
+
private js;
|
|
32
|
+
private readonly consumers;
|
|
22
33
|
private readonly logger;
|
|
34
|
+
private eventSubjectPrefix;
|
|
23
35
|
constructor(meta: {
|
|
24
36
|
name: string;
|
|
25
37
|
version: string;
|
|
26
38
|
description: string | undefined;
|
|
27
|
-
}, logger?: Logger
|
|
39
|
+
}, logger?: Logger, options?: {
|
|
40
|
+
eventSubjectPrefix?: string;
|
|
41
|
+
});
|
|
28
42
|
getLogger(module?: string): pino.Logger<never, boolean>;
|
|
29
43
|
getNc(): NatsConnection;
|
|
30
44
|
init(natsURI: string): Promise<void>;
|
|
45
|
+
private getJetStream;
|
|
46
|
+
publish(event: DomainEvent): Promise<void>;
|
|
47
|
+
subscribe(streamName: string, consumerName: string, handler: EventHandler): Promise<void>;
|
|
31
48
|
stop(): Promise<void>;
|
|
32
49
|
addEndpoint(name: string, handler: (context_: RequestContext, data: Uint8Array) => Promise<Uint8Array>): void;
|
|
33
50
|
/**
|
|
@@ -75,4 +92,4 @@ declare class CallError extends Error {
|
|
|
75
92
|
constructor(message: string, target: string, payload: Uint8Array);
|
|
76
93
|
}
|
|
77
94
|
|
|
78
|
-
export { CallError, Kmicro, RequestContext, init };
|
|
95
|
+
export { CallError, type DomainEvent, type EventHandler, Kmicro, RequestContext, init };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
// src/KMicro.ts
|
|
2
2
|
import assert from "assert";
|
|
3
|
+
import {
|
|
4
|
+
jetstream
|
|
5
|
+
} from "@nats-io/jetstream";
|
|
3
6
|
import { Svcm } from "@nats-io/services";
|
|
4
7
|
import { connect, headers } from "@nats-io/transport-node";
|
|
5
8
|
import {
|
|
@@ -27,14 +30,20 @@ async function init(nats, serviceName, version, description, logger) {
|
|
|
27
30
|
return kmicro;
|
|
28
31
|
}
|
|
29
32
|
var Kmicro = class {
|
|
30
|
-
constructor(meta, logger) {
|
|
33
|
+
constructor(meta, logger, options) {
|
|
31
34
|
this.meta = meta;
|
|
32
35
|
this.logger = logger ?? pino.pino();
|
|
36
|
+
if (options?.eventSubjectPrefix) {
|
|
37
|
+
this.eventSubjectPrefix = options.eventSubjectPrefix;
|
|
38
|
+
}
|
|
33
39
|
}
|
|
34
40
|
service;
|
|
35
41
|
group;
|
|
36
42
|
nc;
|
|
43
|
+
js;
|
|
44
|
+
consumers = [];
|
|
37
45
|
logger;
|
|
46
|
+
eventSubjectPrefix = "events";
|
|
38
47
|
getLogger(module) {
|
|
39
48
|
return this.logger.child({ module });
|
|
40
49
|
}
|
|
@@ -58,7 +67,134 @@ var Kmicro = class {
|
|
|
58
67
|
});
|
|
59
68
|
this.group = this.service.addGroup(this.meta.name);
|
|
60
69
|
}
|
|
70
|
+
getJetStream() {
|
|
71
|
+
assert(this.nc);
|
|
72
|
+
if (!this.js) {
|
|
73
|
+
this.js = jetstream(this.nc);
|
|
74
|
+
}
|
|
75
|
+
return this.js;
|
|
76
|
+
}
|
|
77
|
+
async publish(event) {
|
|
78
|
+
assert(this.nc);
|
|
79
|
+
const js = this.getJetStream();
|
|
80
|
+
const subject = `${this.eventSubjectPrefix}.${event.orgId}.${event.domain}`;
|
|
81
|
+
const tracer = trace.getTracer(this.meta.name, this.meta.version);
|
|
82
|
+
await tracer.startActiveSpan(
|
|
83
|
+
`publish: ${subject}`,
|
|
84
|
+
{ kind: SpanKind.PRODUCER },
|
|
85
|
+
async (span) => {
|
|
86
|
+
try {
|
|
87
|
+
const body = JSON.stringify({
|
|
88
|
+
id: event.id,
|
|
89
|
+
domain: event.domain,
|
|
90
|
+
type: event.type,
|
|
91
|
+
orgId: event.orgId,
|
|
92
|
+
payload: Array.from(event.payload)
|
|
93
|
+
});
|
|
94
|
+
await js.publish(subject, Buffer.from(body), {
|
|
95
|
+
msgID: event.id
|
|
96
|
+
});
|
|
97
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
98
|
+
} catch (error_) {
|
|
99
|
+
span.recordException(error_);
|
|
100
|
+
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
101
|
+
throw error_;
|
|
102
|
+
} finally {
|
|
103
|
+
span.end();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
async subscribe(streamName, consumerName, handler) {
|
|
109
|
+
const js = this.getJetStream();
|
|
110
|
+
const consumer = await js.consumers.get(streamName, consumerName);
|
|
111
|
+
const messages = await consumer.consume();
|
|
112
|
+
this.consumers.push(messages);
|
|
113
|
+
(async () => {
|
|
114
|
+
for await (const msg of messages) {
|
|
115
|
+
const tracer = trace.getTracer(this.meta.name, this.meta.version);
|
|
116
|
+
const contextWithOtel = propagation.extract(
|
|
117
|
+
context.active(),
|
|
118
|
+
msg.headers,
|
|
119
|
+
{
|
|
120
|
+
get(carrier, key) {
|
|
121
|
+
return carrier?.get(key);
|
|
122
|
+
},
|
|
123
|
+
keys(carrier) {
|
|
124
|
+
return carrier?.keys() ?? [];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
await tracer.startActiveSpan(
|
|
129
|
+
`event: ${streamName}.${consumerName}`,
|
|
130
|
+
{ kind: SpanKind.CONSUMER },
|
|
131
|
+
contextWithOtel,
|
|
132
|
+
async (span) => {
|
|
133
|
+
try {
|
|
134
|
+
let event;
|
|
135
|
+
try {
|
|
136
|
+
const parsed = JSON.parse(Buffer.from(msg.data).toString());
|
|
137
|
+
event = {
|
|
138
|
+
id: parsed.id,
|
|
139
|
+
domain: parsed.domain,
|
|
140
|
+
type: parsed.type,
|
|
141
|
+
orgId: parsed.orgId,
|
|
142
|
+
entityId: parsed.entityId,
|
|
143
|
+
payload: new Uint8Array(parsed.payload)
|
|
144
|
+
};
|
|
145
|
+
} catch {
|
|
146
|
+
this.logger.error(
|
|
147
|
+
"failed to unmarshal domain event, terminating message"
|
|
148
|
+
);
|
|
149
|
+
msg.term();
|
|
150
|
+
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const header = {};
|
|
154
|
+
for (const key of msg.headers?.keys() ?? []) {
|
|
155
|
+
if (msg.headers?.has(key)) {
|
|
156
|
+
header[key] = msg.headers?.get(key);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const spanLogger = this.logger.child({
|
|
160
|
+
event: `${event.domain}.${event.type}`,
|
|
161
|
+
spanId: span.spanContext().spanId,
|
|
162
|
+
traceId: span.spanContext().traceId
|
|
163
|
+
});
|
|
164
|
+
const requestContext = new RequestContext(
|
|
165
|
+
contextWithOtel,
|
|
166
|
+
span,
|
|
167
|
+
this.getNc(),
|
|
168
|
+
spanLogger,
|
|
169
|
+
{
|
|
170
|
+
callDepth: 0,
|
|
171
|
+
currentService: this.meta.name,
|
|
172
|
+
header
|
|
173
|
+
}
|
|
174
|
+
);
|
|
175
|
+
await handler(requestContext, event);
|
|
176
|
+
msg.ack();
|
|
177
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
178
|
+
} catch (error_) {
|
|
179
|
+
this.logger.error(
|
|
180
|
+
{ err: error_ },
|
|
181
|
+
`error in event handler: ${error_?.message}`
|
|
182
|
+
);
|
|
183
|
+
span.recordException(error_);
|
|
184
|
+
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
185
|
+
msg.nak();
|
|
186
|
+
} finally {
|
|
187
|
+
span.end();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
})();
|
|
193
|
+
}
|
|
61
194
|
async stop() {
|
|
195
|
+
for (const consumer of this.consumers) {
|
|
196
|
+
consumer.close();
|
|
197
|
+
}
|
|
62
198
|
await this.service?.stop().catch((error) => {
|
|
63
199
|
console.error(error);
|
|
64
200
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/KMicro.ts"],"sourcesContent":["import assert from \"node:assert\";\nimport { type Service, type ServiceGroup, Svcm } from \"@nats-io/services\";\nimport { connect, headers, type NatsConnection } from \"@nats-io/transport-node\";\nimport {\n\ttype Context,\n\tcontext,\n\tpropagation,\n\ttype Span,\n\tSpanKind,\n\tSpanStatusCode,\n\ttrace,\n} from \"@opentelemetry/api\";\nimport {\n\tATTR_RPC_METHOD,\n\tATTR_RPC_SERVICE,\n} from \"@opentelemetry/semantic-conventions/incubating\";\nimport pino, { type Logger } from \"pino\";\n\n/**\n * Use init to create a kmicro instance and directly start (init) it\n */\nexport async function init(\n\tnats: string,\n\tserviceName: string,\n\tversion: string,\n\tdescription?: string,\n\tlogger?: Logger,\n) {\n\tconst kmicro = new Kmicro(\n\t\t{\n\t\t\tname: serviceName,\n\t\t\tversion,\n\t\t\tdescription,\n\t\t},\n\t\tlogger,\n\t);\n\tawait kmicro.init(nats);\n\treturn kmicro;\n}\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\ninterface Callable {\n\tcall(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t},\n\t): Promise<Uint8Array>;\n}\n\nexport class Kmicro implements Callable {\n\tprivate service: Service | undefined;\n\tprivate group: ServiceGroup | undefined;\n\tprivate nc: NatsConnection | undefined;\n\tprivate readonly logger: Logger;\n\n\tconstructor(\n\t\tprivate readonly meta: {\n\t\t\tname: string;\n\t\t\tversion: string;\n\t\t\tdescription: string | undefined;\n\t\t},\n\t\tlogger?: Logger,\n\t) {\n\t\tthis.logger = logger ?? pino.pino();\n\t}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.logger.child({ module });\n\t}\n\n\tpublic getNc(): NatsConnection {\n\t\tassert(this.nc);\n\t\treturn this.nc;\n\t}\n\n\tpublic async init(natsURI: string) {\n\t\tconst natsUrl = new URL(natsURI);\n\t\tthis.nc = await connect({\n\t\t\tname: this.meta.name,\n\t\t\tuser: natsUrl.username,\n\t\t\tpass: natsUrl.password,\n\t\t\tservers: [natsUrl.host],\n\t\t});\n\t\tconst svc = new Svcm(this.nc);\n\t\tthis.service = await svc.add({\n\t\t\tname: this.meta.name,\n\t\t\tversion: this.meta.version,\n\t\t\tdescription: this.meta.description,\n\t\t});\n\t\tthis.group = this.service.addGroup(this.meta.name);\n\t}\n\n\tpublic async stop() {\n\t\tawait this.service?.stop().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t\tawait this.nc?.close().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t}\n\n\tpublic addEndpoint(\n\t\tname: string,\n\t\thandler: (\n\t\t\tcontext_: RequestContext,\n\t\t\tdata: Uint8Array,\n\t\t) => Promise<Uint8Array>,\n\t) {\n\t\tassert(this.group);\n\n\t\tthis.group.addEndpoint(name, async (error, message) => {\n\t\t\tassert(this.nc);\n\t\t\tif (error) {\n\t\t\t\tconsole.error(error);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Prevent infinite loops\n\t\t\tconst currentCallDepth = Number.parseInt(\n\t\t\t\tmessage.headers?.get(\"kmc-depth\") ?? \"0\",\n\t\t\t\t10,\n\t\t\t);\n\t\t\tif (currentCallDepth >= 20) {\n\t\t\t\tthrow new Error(`max call depth reached: ${currentCallDepth}`);\n\t\t\t}\n\n\t\t\tconst contextWithOtel: Context = propagation.extract(\n\t\t\t\tcontext.active(),\n\t\t\t\tmessage.headers,\n\t\t\t\t{\n\t\t\t\t\tget(carrier, key) {\n\t\t\t\t\t\treturn carrier?.get(key);\n\t\t\t\t\t},\n\t\t\t\t\tkeys(carrier) {\n\t\t\t\t\t\treturn carrier?.keys() ?? [];\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst tracer = trace.getTracer(this.meta.name, this.meta.version);\n\t\t\tconst spanName = `handle: ${this.meta.name}.${name}`;\n\t\t\tawait tracer.startActiveSpan(\n\t\t\t\tspanName,\n\t\t\t\t{\n\t\t\t\t\tkind: SpanKind.SERVER,\n\t\t\t\t},\n\t\t\t\tcontextWithOtel,\n\t\t\t\tasync (span) => {\n\t\t\t\t\tconst spanLogger = this.logger.child({\n\t\t\t\t\t\taction: name,\n\t\t\t\t\t\tspanId: span.spanContext().spanId,\n\t\t\t\t\t\ttraceId: span.spanContext().traceId,\n\t\t\t\t\t});\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst header: Record<string, string> = {};\n\t\t\t\t\t\tfor (const key of message.headers?.keys() ?? []) {\n\t\t\t\t\t\t\tif (message.headers?.has(key)) {\n\t\t\t\t\t\t\t\theader[key] = message.headers?.get(key);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst requestContext = new RequestContext(\n\t\t\t\t\t\t\tcontextWithOtel,\n\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: Checked with assert\n\t\t\t\t\t\t\tthis.nc!,\n\t\t\t\t\t\t\tspanLogger,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcallDepth: currentCallDepth,\n\t\t\t\t\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst result = await handler(requestContext, message.data);\n\t\t\t\t\t\tmessage.respond(result);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t\t} catch (error_) {\n\t\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\terr: error_,\n\t\t\t\t\t\t\t\taction: name,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t`error in handler: ${(error_ as Error)?.message}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tspan.recordException(error_ as Error);\n\t\t\t\t\t\tmessage.respondError(500, (error_ as Error).message);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tspan.end();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Start a new call\n\t */\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t\tmoleculerTrace?: {\n\t\t\t\ttraceId?: string | undefined;\n\t\t\t\tparentId?: string | undefined;\n\t\t\t};\n\t\t},\n\t): Promise<Uint8Array> {\n\t\tassert(this.nc);\n\n\t\tlet trace:\n\t\t\t| undefined\n\t\t\t| {\n\t\t\t\t\ttraceId: string;\n\t\t\t\t\tparentId: string;\n\t\t\t };\n\t\tif (options?.moleculerTrace) {\n\t\t\t// we have to shorten the moleculer trace id because the jaeger exporter uses only 16 chars\n\t\t\tconst molTraceId = options.moleculerTrace.traceId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\tconst traceId = Array.from({ length: 16 })\n\t\t\t\t.fill(\"0\")\n\t\t\t\t.join(\"\")\n\t\t\t\t.concat(molTraceId ?? \"\");\n\t\t\tconst molParentId = options.moleculerTrace.parentId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\ttrace = {\n\t\t\t\ttraceId,\n\t\t\t\tparentId: molParentId ?? \"\",\n\t\t\t};\n\t\t}\n\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: 0,\n\t\t\t\tcontext: undefined,\n\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\theader: options?.header ?? {},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttimeout: options?.timeout,\n\t\t\t\ttrace,\n\t\t\t},\n\t\t);\n\t}\n}\n\nexport class RequestContext {\n\t// eslint-disable-next-line max-params\n\tconstructor(\n\t\treadonly context: Context,\n\t\treadonly span: Span,\n\t\treadonly nc: NatsConnection,\n\t\tprivate readonly logger: Logger,\n\t\treadonly meta: {\n\t\t\tcallDepth: number;\n\t\t\tcurrentService: string;\n\t\t\theader: Record<string, string>;\n\t\t},\n\t) {}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.logger.child({\n\t\t\tmodule,\n\t\t});\n\t}\n\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t},\n\t): Promise<Uint8Array> {\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: this.meta.callDepth,\n\t\t\t\tcontext: this.context,\n\t\t\t\tcurrentService: this.meta.currentService,\n\t\t\t\theader: this.meta.header,\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n}\n\nexport class CallError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tprivate readonly target: string,\n\t\tprivate readonly payload: Uint8Array,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CallError\";\n\t}\n}\n\n// eslint-disable-next-line max-params\nasync function doCall(\n\tnc: NatsConnection,\n\ttarget: string,\n\tpayload: Uint8Array,\n\tmeta: {\n\t\tcallDepth: number;\n\t\t/**\n\t\t * The otel context\n\t\t */\n\t\tcontext: Context | undefined;\n\t\tcurrentService: string;\n\t\t/**\n\t\t * Headers from the parent calls\n\t\t */\n\t\theader: Record<string, string>;\n\t},\n\toptions?: {\n\t\t/**\n\t\t * @default 5000 ms\n\t\t */\n\t\ttimeout?: number;\n\t\theader?: Record<string, string>;\n\t\t/**\n\t\t * Optionally pass an existing trace from the moleculer framework\n\t\t */\n\t\ttrace?: {\n\t\t\t/**\n\t\t\t * This is the ID of the whole trace forest and is used to uniquely identify a distributed trace through a system.\n\t\t\t */\n\t\t\ttraceId: string | undefined;\n\t\t\t/**\n\t\t\t * or span id: This is the ID of this request as known by the caller\n\t\t\t */\n\t\t\tparentId: string | undefined;\n\t\t};\n\t},\n): Promise<Uint8Array> {\n\tif (meta.callDepth >= 20) {\n\t\tthrow new Error(`max call depth reached: ${meta.callDepth}`);\n\t}\n\n\tconst carrierData: Context | { traceparent?: string } = meta.context ?? {};\n\tif (options?.trace && !meta.context) {\n\t\tconst version = Buffer.alloc(1).toString(\"hex\");\n\t\tconst flags = \"01\"; // means sampled\n\t\tconst header = `${version}-${options.trace.traceId}-${options.trace.parentId}-${flags}`;\n\t\t(carrierData as { traceparent?: string | undefined }).traceparent = header;\n\t}\n\n\tconst callingContext: Context = propagation.extract(\n\t\tcontext.active(),\n\t\tcarrierData,\n\t);\n\tconst tracer = trace.getTracer(\"default\");\n\tconst [service, action] = target.split(\".\");\n\treturn tracer.startActiveSpan(\n\t\t`call: ${target}`,\n\t\t{\n\t\t\tkind: SpanKind.CLIENT,\n\t\t\tattributes: {\n\t\t\t\t[ATTR_RPC_SERVICE]: service,\n\t\t\t\t[ATTR_RPC_METHOD]: action,\n\t\t\t},\n\t\t},\n\t\tcallingContext,\n\t\tasync (span) => {\n\t\t\t// Add kmicro and otel headers to the nats message headers\n\t\t\tconst natsHeadersMap = headers();\n\t\t\tnatsHeadersMap.set(\"kmc-depth\", (meta.callDepth + 1).toFixed(0));\n\t\t\tpropagation.inject(context.active(), natsHeadersMap, {\n\t\t\t\tset(carrier, key, value) {\n\t\t\t\t\tcarrier.set(key, value);\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst mergedHeaders = { ...meta.header, ...options?.header };\n\t\t\tfor (const key in mergedHeaders) {\n\t\t\t\tif (!Object.hasOwn(mergedHeaders, key)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (mergedHeaders[key]) {\n\t\t\t\t\tnatsHeadersMap.set(key, mergedHeaders[key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await nc.request(target, payload, {\n\t\t\t\t\theaders: natsHeadersMap,\n\t\t\t\t\ttimeout: options?.timeout ?? 5000,\n\t\t\t\t});\n\t\t\t\tif (result.headers?.get(\"Nats-Service-Error-Code\")) {\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\tspan.recordException(result.headers.get(\"Nats-Service-Error\"));\n\t\t\t\t\tthrow new CallError(\n\t\t\t\t\t\t`received error: ${result.headers.get(\"Nats-Service-Error\")}`,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tpayload,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\treturn result.data;\n\t\t\t} finally {\n\t\t\t\tspan.end();\n\t\t\t}\n\t\t},\n\t);\n}\n"],"mappings":"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","names":["trace","context"]}
|
|
1
|
+
{"version":3,"sources":["../src/KMicro.ts"],"sourcesContent":["import assert from \"node:assert\";\nimport {\n\ttype ConsumerMessages,\n\ttype JetStreamClient,\n\tjetstream,\n} from \"@nats-io/jetstream\";\nimport { type Service, type ServiceGroup, Svcm } from \"@nats-io/services\";\nimport { connect, headers, type NatsConnection } from \"@nats-io/transport-node\";\nimport {\n\ttype Context,\n\tcontext,\n\tpropagation,\n\ttype Span,\n\tSpanKind,\n\tSpanStatusCode,\n\ttrace,\n} from \"@opentelemetry/api\";\nimport {\n\tATTR_RPC_METHOD,\n\tATTR_RPC_SERVICE,\n} from \"@opentelemetry/semantic-conventions/incubating\";\nimport pino, { type Logger } from \"pino\";\n\n/**\n * Use init to create a kmicro instance and directly start (init) it\n */\nexport async function init(\n\tnats: string,\n\tserviceName: string,\n\tversion: string,\n\tdescription?: string,\n\tlogger?: Logger,\n) {\n\tconst kmicro = new Kmicro(\n\t\t{\n\t\t\tname: serviceName,\n\t\t\tversion,\n\t\t\tdescription,\n\t\t},\n\t\tlogger,\n\t);\n\tawait kmicro.init(nats);\n\treturn kmicro;\n}\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\ninterface Callable {\n\tcall(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t},\n\t): Promise<Uint8Array>;\n}\n\nexport type DomainEvent = {\n\tid: string;\n\tdomain: string;\n\ttype: string;\n\torgId: string;\n\tentityId: string;\n\tpayload: Uint8Array;\n};\n\nexport type EventHandler = (\n\tcontext_: RequestContext,\n\tevent: DomainEvent,\n) => Promise<void>;\n\nexport class Kmicro implements Callable {\n\tprivate service: Service | undefined;\n\tprivate group: ServiceGroup | undefined;\n\tprivate nc: NatsConnection | undefined;\n\tprivate js: JetStreamClient | undefined;\n\tprivate readonly consumers: ConsumerMessages[] = [];\n\tprivate readonly logger: Logger;\n\tprivate eventSubjectPrefix = \"events\";\n\n\tconstructor(\n\t\tprivate readonly meta: {\n\t\t\tname: string;\n\t\t\tversion: string;\n\t\t\tdescription: string | undefined;\n\t\t},\n\t\tlogger?: Logger,\n\t\toptions?: {\n\t\t\teventSubjectPrefix?: string;\n\t\t},\n\t) {\n\t\tthis.logger = logger ?? pino.pino();\n\t\tif (options?.eventSubjectPrefix) {\n\t\t\tthis.eventSubjectPrefix = options.eventSubjectPrefix;\n\t\t}\n\t}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.logger.child({ module });\n\t}\n\n\tpublic getNc(): NatsConnection {\n\t\tassert(this.nc);\n\t\treturn this.nc;\n\t}\n\n\tpublic async init(natsURI: string) {\n\t\tconst natsUrl = new URL(natsURI);\n\t\tthis.nc = await connect({\n\t\t\tname: this.meta.name,\n\t\t\tuser: natsUrl.username,\n\t\t\tpass: natsUrl.password,\n\t\t\tservers: [natsUrl.host],\n\t\t});\n\t\tconst svc = new Svcm(this.nc);\n\t\tthis.service = await svc.add({\n\t\t\tname: this.meta.name,\n\t\t\tversion: this.meta.version,\n\t\t\tdescription: this.meta.description,\n\t\t});\n\t\tthis.group = this.service.addGroup(this.meta.name);\n\t}\n\n\tprivate getJetStream(): JetStreamClient {\n\t\tassert(this.nc);\n\t\tif (!this.js) {\n\t\t\tthis.js = jetstream(this.nc);\n\t\t}\n\t\treturn this.js;\n\t}\n\n\tpublic async publish(event: DomainEvent): Promise<void> {\n\t\tassert(this.nc);\n\t\tconst js = this.getJetStream();\n\t\tconst subject = `${this.eventSubjectPrefix}.${event.orgId}.${event.domain}`;\n\n\t\tconst tracer = trace.getTracer(this.meta.name, this.meta.version);\n\t\tawait tracer.startActiveSpan(\n\t\t\t`publish: ${subject}`,\n\t\t\t{ kind: SpanKind.PRODUCER },\n\t\t\tasync (span) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst body = JSON.stringify({\n\t\t\t\t\t\tid: event.id,\n\t\t\t\t\t\tdomain: event.domain,\n\t\t\t\t\t\ttype: event.type,\n\t\t\t\t\t\torgId: event.orgId,\n\t\t\t\t\t\tpayload: Array.from(event.payload),\n\t\t\t\t\t});\n\n\t\t\t\t\tawait js.publish(subject, Buffer.from(body), {\n\t\t\t\t\t\tmsgID: event.id,\n\t\t\t\t\t});\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t} catch (error_) {\n\t\t\t\t\tspan.recordException(error_ as Error);\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\tthrow error_;\n\t\t\t\t} finally {\n\t\t\t\t\tspan.end();\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t}\n\n\tpublic async subscribe(\n\t\tstreamName: string,\n\t\tconsumerName: string,\n\t\thandler: EventHandler,\n\t): Promise<void> {\n\t\tconst js = this.getJetStream();\n\t\tconst consumer = await js.consumers.get(streamName, consumerName);\n\t\tconst messages = await consumer.consume();\n\t\tthis.consumers.push(messages);\n\n\t\t(async () => {\n\t\t\tfor await (const msg of messages) {\n\t\t\t\tconst tracer = trace.getTracer(this.meta.name, this.meta.version);\n\n\t\t\t\tconst contextWithOtel: Context = propagation.extract(\n\t\t\t\t\tcontext.active(),\n\t\t\t\t\tmsg.headers,\n\t\t\t\t\t{\n\t\t\t\t\t\tget(carrier, key) {\n\t\t\t\t\t\t\treturn carrier?.get(key);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tkeys(carrier) {\n\t\t\t\t\t\t\treturn carrier?.keys() ?? [];\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tawait tracer.startActiveSpan(\n\t\t\t\t\t`event: ${streamName}.${consumerName}`,\n\t\t\t\t\t{ kind: SpanKind.CONSUMER },\n\t\t\t\t\tcontextWithOtel,\n\t\t\t\t\tasync (span) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tlet event: DomainEvent;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst parsed = JSON.parse(Buffer.from(msg.data).toString());\n\t\t\t\t\t\t\t\tevent = {\n\t\t\t\t\t\t\t\t\tid: parsed.id,\n\t\t\t\t\t\t\t\t\tdomain: parsed.domain,\n\t\t\t\t\t\t\t\t\ttype: parsed.type,\n\t\t\t\t\t\t\t\t\torgId: parsed.orgId,\n\t\t\t\t\t\t\t\t\tentityId: parsed.entityId,\n\t\t\t\t\t\t\t\t\tpayload: new Uint8Array(parsed.payload),\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t\t\t\t\"failed to unmarshal domain event, terminating message\",\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tmsg.term();\n\t\t\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst header: Record<string, string> = {};\n\t\t\t\t\t\t\tfor (const key of msg.headers?.keys() ?? []) {\n\t\t\t\t\t\t\t\tif (msg.headers?.has(key)) {\n\t\t\t\t\t\t\t\t\theader[key] = msg.headers?.get(key);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst spanLogger = this.logger.child({\n\t\t\t\t\t\t\t\tevent: `${event.domain}.${event.type}`,\n\t\t\t\t\t\t\t\tspanId: span.spanContext().spanId,\n\t\t\t\t\t\t\t\ttraceId: span.spanContext().traceId,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tconst requestContext = new RequestContext(\n\t\t\t\t\t\t\t\tcontextWithOtel,\n\t\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t\tthis.getNc(),\n\t\t\t\t\t\t\t\tspanLogger,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tcallDepth: 0,\n\t\t\t\t\t\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tawait handler(requestContext, event);\n\t\t\t\t\t\t\tmsg.ack();\n\t\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t\t\t} catch (error_) {\n\t\t\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t\t\t{ err: error_ },\n\t\t\t\t\t\t\t\t`error in event handler: ${(error_ as Error)?.message}`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tspan.recordException(error_ as Error);\n\t\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\t\t\tmsg.nak();\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tspan.end();\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t})();\n\t}\n\n\tpublic async stop() {\n\t\tfor (const consumer of this.consumers) {\n\t\t\tconsumer.close();\n\t\t}\n\t\tawait this.service?.stop().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t\tawait this.nc?.close().catch((error: unknown) => {\n\t\t\tconsole.error(error);\n\t\t});\n\t}\n\n\tpublic addEndpoint(\n\t\tname: string,\n\t\thandler: (\n\t\t\tcontext_: RequestContext,\n\t\t\tdata: Uint8Array,\n\t\t) => Promise<Uint8Array>,\n\t) {\n\t\tassert(this.group);\n\n\t\tthis.group.addEndpoint(name, async (error, message) => {\n\t\t\tassert(this.nc);\n\t\t\tif (error) {\n\t\t\t\tconsole.error(error);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Prevent infinite loops\n\t\t\tconst currentCallDepth = Number.parseInt(\n\t\t\t\tmessage.headers?.get(\"kmc-depth\") ?? \"0\",\n\t\t\t\t10,\n\t\t\t);\n\t\t\tif (currentCallDepth >= 20) {\n\t\t\t\tthrow new Error(`max call depth reached: ${currentCallDepth}`);\n\t\t\t}\n\n\t\t\tconst contextWithOtel: Context = propagation.extract(\n\t\t\t\tcontext.active(),\n\t\t\t\tmessage.headers,\n\t\t\t\t{\n\t\t\t\t\tget(carrier, key) {\n\t\t\t\t\t\treturn carrier?.get(key);\n\t\t\t\t\t},\n\t\t\t\t\tkeys(carrier) {\n\t\t\t\t\t\treturn carrier?.keys() ?? [];\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst tracer = trace.getTracer(this.meta.name, this.meta.version);\n\t\t\tconst spanName = `handle: ${this.meta.name}.${name}`;\n\t\t\tawait tracer.startActiveSpan(\n\t\t\t\tspanName,\n\t\t\t\t{\n\t\t\t\t\tkind: SpanKind.SERVER,\n\t\t\t\t},\n\t\t\t\tcontextWithOtel,\n\t\t\t\tasync (span) => {\n\t\t\t\t\tconst spanLogger = this.logger.child({\n\t\t\t\t\t\taction: name,\n\t\t\t\t\t\tspanId: span.spanContext().spanId,\n\t\t\t\t\t\ttraceId: span.spanContext().traceId,\n\t\t\t\t\t});\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst header: Record<string, string> = {};\n\t\t\t\t\t\tfor (const key of message.headers?.keys() ?? []) {\n\t\t\t\t\t\t\tif (message.headers?.has(key)) {\n\t\t\t\t\t\t\t\theader[key] = message.headers?.get(key);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst requestContext = new RequestContext(\n\t\t\t\t\t\t\tcontextWithOtel,\n\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: Checked with assert\n\t\t\t\t\t\t\tthis.nc!,\n\t\t\t\t\t\t\tspanLogger,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcallDepth: currentCallDepth,\n\t\t\t\t\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\t\t\t\t\theader,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst result = await handler(requestContext, message.data);\n\t\t\t\t\t\tmessage.respond(result);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t\t} catch (error_) {\n\t\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\terr: error_,\n\t\t\t\t\t\t\t\taction: name,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t`error in handler: ${(error_ as Error)?.message}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tspan.recordException(error_ as Error);\n\t\t\t\t\t\tmessage.respondError(500, (error_ as Error).message);\n\t\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tspan.end();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Start a new call\n\t */\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t\tmoleculerTrace?: {\n\t\t\t\ttraceId?: string | undefined;\n\t\t\t\tparentId?: string | undefined;\n\t\t\t};\n\t\t},\n\t): Promise<Uint8Array> {\n\t\tassert(this.nc);\n\n\t\tlet trace:\n\t\t\t| undefined\n\t\t\t| {\n\t\t\t\t\ttraceId: string;\n\t\t\t\t\tparentId: string;\n\t\t\t };\n\t\tif (options?.moleculerTrace) {\n\t\t\t// we have to shorten the moleculer trace id because the jaeger exporter uses only 16 chars\n\t\t\tconst molTraceId = options.moleculerTrace.traceId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\tconst traceId = Array.from({ length: 16 })\n\t\t\t\t.fill(\"0\")\n\t\t\t\t.join(\"\")\n\t\t\t\t.concat(molTraceId ?? \"\");\n\t\t\tconst molParentId = options.moleculerTrace.parentId\n\t\t\t\t?.replaceAll(\"-\", \"\")\n\t\t\t\t.slice(0, 16);\n\t\t\ttrace = {\n\t\t\t\ttraceId,\n\t\t\t\tparentId: molParentId ?? \"\",\n\t\t\t};\n\t\t}\n\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: 0,\n\t\t\t\tcontext: undefined,\n\t\t\t\tcurrentService: this.meta.name,\n\t\t\t\theader: options?.header ?? {},\n\t\t\t},\n\t\t\t{\n\t\t\t\ttimeout: options?.timeout,\n\t\t\t\ttrace,\n\t\t\t},\n\t\t);\n\t}\n}\n\nexport class RequestContext {\n\t// eslint-disable-next-line max-params\n\tconstructor(\n\t\treadonly context: Context,\n\t\treadonly span: Span,\n\t\treadonly nc: NatsConnection,\n\t\tprivate readonly logger: Logger,\n\t\treadonly meta: {\n\t\t\tcallDepth: number;\n\t\t\tcurrentService: string;\n\t\t\theader: Record<string, string>;\n\t\t},\n\t) {}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.logger.child({\n\t\t\tmodule,\n\t\t});\n\t}\n\n\tpublic async call(\n\t\ttarget: string,\n\t\tpayload: Uint8Array,\n\t\toptions?: {\n\t\t\t/**\n\t\t\t * @default 5000 ms\n\t\t\t */\n\t\t\ttimeout?: number;\n\t\t\theader?: Record<string, string>;\n\t\t},\n\t): Promise<Uint8Array> {\n\t\treturn doCall(\n\t\t\tthis.nc,\n\t\t\ttarget,\n\t\t\tpayload,\n\t\t\t{\n\t\t\t\tcallDepth: this.meta.callDepth,\n\t\t\t\tcontext: this.context,\n\t\t\t\tcurrentService: this.meta.currentService,\n\t\t\t\theader: this.meta.header,\n\t\t\t},\n\t\t\toptions,\n\t\t);\n\t}\n}\n\nexport class CallError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tprivate readonly target: string,\n\t\tprivate readonly payload: Uint8Array,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"CallError\";\n\t}\n}\n\n// eslint-disable-next-line max-params\nasync function doCall(\n\tnc: NatsConnection,\n\ttarget: string,\n\tpayload: Uint8Array,\n\tmeta: {\n\t\tcallDepth: number;\n\t\t/**\n\t\t * The otel context\n\t\t */\n\t\tcontext: Context | undefined;\n\t\tcurrentService: string;\n\t\t/**\n\t\t * Headers from the parent calls\n\t\t */\n\t\theader: Record<string, string>;\n\t},\n\toptions?: {\n\t\t/**\n\t\t * @default 5000 ms\n\t\t */\n\t\ttimeout?: number;\n\t\theader?: Record<string, string>;\n\t\t/**\n\t\t * Optionally pass an existing trace from the moleculer framework\n\t\t */\n\t\ttrace?: {\n\t\t\t/**\n\t\t\t * This is the ID of the whole trace forest and is used to uniquely identify a distributed trace through a system.\n\t\t\t */\n\t\t\ttraceId: string | undefined;\n\t\t\t/**\n\t\t\t * or span id: This is the ID of this request as known by the caller\n\t\t\t */\n\t\t\tparentId: string | undefined;\n\t\t};\n\t},\n): Promise<Uint8Array> {\n\tif (meta.callDepth >= 20) {\n\t\tthrow new Error(`max call depth reached: ${meta.callDepth}`);\n\t}\n\n\tconst carrierData: Context | { traceparent?: string } = meta.context ?? {};\n\tif (options?.trace && !meta.context) {\n\t\tconst version = Buffer.alloc(1).toString(\"hex\");\n\t\tconst flags = \"01\"; // means sampled\n\t\tconst header = `${version}-${options.trace.traceId}-${options.trace.parentId}-${flags}`;\n\t\t(carrierData as { traceparent?: string | undefined }).traceparent = header;\n\t}\n\n\tconst callingContext: Context = propagation.extract(\n\t\tcontext.active(),\n\t\tcarrierData,\n\t);\n\tconst tracer = trace.getTracer(\"default\");\n\tconst [service, action] = target.split(\".\");\n\treturn tracer.startActiveSpan(\n\t\t`call: ${target}`,\n\t\t{\n\t\t\tkind: SpanKind.CLIENT,\n\t\t\tattributes: {\n\t\t\t\t[ATTR_RPC_SERVICE]: service,\n\t\t\t\t[ATTR_RPC_METHOD]: action,\n\t\t\t},\n\t\t},\n\t\tcallingContext,\n\t\tasync (span) => {\n\t\t\t// Add kmicro and otel headers to the nats message headers\n\t\t\tconst natsHeadersMap = headers();\n\t\t\tnatsHeadersMap.set(\"kmc-depth\", (meta.callDepth + 1).toFixed(0));\n\t\t\tpropagation.inject(context.active(), natsHeadersMap, {\n\t\t\t\tset(carrier, key, value) {\n\t\t\t\t\tcarrier.set(key, value);\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst mergedHeaders = { ...meta.header, ...options?.header };\n\t\t\tfor (const key in mergedHeaders) {\n\t\t\t\tif (!Object.hasOwn(mergedHeaders, key)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (mergedHeaders[key]) {\n\t\t\t\t\tnatsHeadersMap.set(key, mergedHeaders[key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await nc.request(target, payload, {\n\t\t\t\t\theaders: natsHeadersMap,\n\t\t\t\t\ttimeout: options?.timeout ?? 5000,\n\t\t\t\t});\n\t\t\t\tif (result.headers?.get(\"Nats-Service-Error-Code\")) {\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\tspan.recordException(result.headers.get(\"Nats-Service-Error\"));\n\t\t\t\t\tthrow new CallError(\n\t\t\t\t\t\t`received error: ${result.headers.get(\"Nats-Service-Error\")}`,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tpayload,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\treturn result.data;\n\t\t\t} finally {\n\t\t\t\tspan.end();\n\t\t\t}\n\t\t},\n\t);\n}\n"],"mappings":"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","names":["trace","context"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kultify/kmicro-js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -49,28 +49,29 @@
|
|
|
49
49
|
"author": "Kultify GmbH",
|
|
50
50
|
"license": "MIT",
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@nats-io/
|
|
53
|
-
"@nats-io/
|
|
52
|
+
"@nats-io/jetstream": "3.3.1",
|
|
53
|
+
"@nats-io/services": "3.3.1",
|
|
54
|
+
"@nats-io/transport-node": "3.3.1",
|
|
54
55
|
"@opentelemetry/api": "^1.9.0",
|
|
55
|
-
"@opentelemetry/semantic-conventions": "^1.
|
|
56
|
-
"pino": "^
|
|
56
|
+
"@opentelemetry/semantic-conventions": "^1.40.0",
|
|
57
|
+
"pino": "^10.3.1"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
|
-
"@biomejs/biome": "2.
|
|
60
|
-
"@opentelemetry/core": "^2.0
|
|
61
|
-
"@opentelemetry/exporter-trace-otlp-proto": "^0.
|
|
62
|
-
"@opentelemetry/instrumentation-pino": "^0.
|
|
63
|
-
"@opentelemetry/resources": "^2.0
|
|
64
|
-
"@opentelemetry/sdk-node": "^0.
|
|
65
|
-
"@opentelemetry/sdk-trace-node": "^2.0
|
|
66
|
-
"@testcontainers/nats": "^11.
|
|
67
|
-
"@tsconfig/node20": "^20.1.
|
|
68
|
-
"@types/node": "^
|
|
60
|
+
"@biomejs/biome": "2.4.6",
|
|
61
|
+
"@opentelemetry/core": "^2.6.0",
|
|
62
|
+
"@opentelemetry/exporter-trace-otlp-proto": "^0.213.0",
|
|
63
|
+
"@opentelemetry/instrumentation-pino": "^0.59.0",
|
|
64
|
+
"@opentelemetry/resources": "^2.6.0",
|
|
65
|
+
"@opentelemetry/sdk-node": "^0.213.0",
|
|
66
|
+
"@opentelemetry/sdk-trace-node": "^2.6.0",
|
|
67
|
+
"@testcontainers/nats": "^11.12.0",
|
|
68
|
+
"@tsconfig/node20": "^20.1.9",
|
|
69
|
+
"@types/node": "^25.4.0",
|
|
69
70
|
"jaeger-client": "^3.19.0",
|
|
70
71
|
"moleculer": "^0.14.35",
|
|
71
|
-
"tsup": "^8.5.
|
|
72
|
-
"typescript": "5.9.
|
|
73
|
-
"vitest": "^
|
|
72
|
+
"tsup": "^8.5.1",
|
|
73
|
+
"typescript": "5.9.3",
|
|
74
|
+
"vitest": "^4.0.18"
|
|
74
75
|
},
|
|
75
76
|
"pnpm": {
|
|
76
77
|
"onlyBuiltDependencies": [
|