@kultify/kmicro-js 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -56,7 +56,6 @@ async function init(nats, serviceName, version, description) {
56
56
  await kmicro.init(nats);
57
57
  return kmicro;
58
58
  }
59
- var codec = (0, import_transport_node.JSONCodec)();
60
59
  var Kmicro = class {
61
60
  constructor(meta) {
62
61
  this.meta = meta;
@@ -155,8 +154,8 @@ var Kmicro = class {
155
154
  currentService: this.meta.name
156
155
  }
157
156
  );
158
- const result = await handler(requestContext, message.json());
159
- message.respond(codec.encode(result));
157
+ const result = await handler(requestContext, message.data);
158
+ message.respond(result);
160
159
  span.setStatus({ code: import_api.SpanStatusCode.OK });
161
160
  } catch (error_) {
162
161
  span.recordException(error_);
@@ -252,7 +251,7 @@ async function doCall(nc, target, payload, meta, options) {
252
251
  }
253
252
  });
254
253
  try {
255
- const result = await nc.request(target, codec.encode(payload), {
254
+ const result = await nc.request(target, payload, {
256
255
  headers: natsHeadersMap,
257
256
  timeout: options?.timeout ?? 5e3
258
257
  });
@@ -266,7 +265,7 @@ async function doCall(nc, target, payload, meta, options) {
266
265
  payload
267
266
  );
268
267
  }
269
- return result.json();
268
+ return result.data;
270
269
  } finally {
271
270
  span.end();
272
271
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/KMicro.ts"],"sourcesContent":["export * from './KMicro.js';\n","import assert from 'node:assert';\nimport {Svc, type Service, type ServiceGroup} from '@nats-io/services';\nimport {\n\tconnect,\n\theaders,\n\tJSONCodec,\n\ttype NatsConnection,\n} from '@nats-io/transport-node';\nimport {\n\tcontext,\n\tpropagation,\n\tSpanKind,\n\tSpanStatusCode,\n\ttrace,\n\ttype Context,\n\ttype Span,\n} from '@opentelemetry/api';\nimport {OTLPTraceExporter} from '@opentelemetry/exporter-trace-otlp-proto';\nimport {Resource} from '@opentelemetry/resources';\nimport {NodeSDK} from '@opentelemetry/sdk-node';\nimport {\n\tATTR_MESSAGING_SYSTEM,\n\tATTR_RPC_METHOD,\n\tATTR_RPC_SERVICE,\n\tATTR_SERVICE_NAME,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport pino, {type Logger} from 'pino';\n\nexport async function init(\n\tnats: string,\n\tserviceName: string,\n\tversion: string,\n\tdescription?: string,\n) {\n\tconst kmicro = new Kmicro({\n\t\tname: serviceName,\n\t\tversion,\n\t\tdescription,\n\t});\n\tawait kmicro.init(nats);\n\treturn kmicro;\n}\n\nconst codec = JSONCodec(); // eslint-disable-line new-cap\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\ninterface Callable {\n\tcall(\n\t\ttarget: string,\n\t\tpayload: Record<string, any>,\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<Record<string, unknown>>;\n}\n\nexport class Kmicro implements Callable {\n\tprivate service: Service | undefined;\n\tprivate group: ServiceGroup | undefined;\n\tprivate nc: NatsConnection | undefined;\n\tprivate otel: NodeSDK | undefined;\n\tprivate readonly pinoLogger: pino.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) {\n\t\tthis.pinoLogger = pino.pino();\n\t}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.pinoLogger.child({module});\n\t}\n\n\tpublic async init(natsConnection: string) {\n\t\tthis.nc = await connect({\n\t\t\tname: this.meta.name,\n\t\t\tservers: natsConnection,\n\t\t});\n\t\tconst svc = new Svc(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\tthis.otel = new NodeSDK({\n\t\t\tserviceName: this.meta.name,\n\t\t\ttraceExporter: new OTLPTraceExporter(),\n\t\t\tresource: new Resource({\n\t\t\t\t[ATTR_SERVICE_NAME]: this.meta.name,\n\t\t\t\t[ATTR_MESSAGING_SYSTEM]: 'nats',\n\t\t\t}),\n\t\t});\n\n\t\tthis.otel.start();\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\tawait this.otel?.shutdown().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: Record<string, any>,\n\t\t) => Promise<Record<string, any>>,\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(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.pinoLogger.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 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\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},\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst result = await handler(requestContext, message.json());\n\t\t\t\t\t\tmessage.respond(codec.encode(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\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: Record<string, any>,\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<Record<string, unknown>> {\n\t\tassert(this.nc);\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},\n\t\t\toptions,\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},\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: Record<string, any>,\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<Record<string, unknown>> {\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},\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: Record<string, unknown>,\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: Record<string, any>,\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},\n\toptions?: {\n\t\t/**\n\t\t * @default 5000 ms\n\t\t */\n\t\ttimeout?: number;\n\t},\n): Promise<Record<string, unknown>> {\n\tif (meta.callDepth >= 20) {\n\t\tthrow new Error('max call depth reached: ' + meta.callDepth);\n\t}\n\n\tconst callingContext: Context = propagation.extract(\n\t\tcontext.active(),\n\t\tmeta.context ?? {},\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\n\t\t\ttry {\n\t\t\t\tconst result = await nc.request(target, codec.encode(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\tspan.setStatus({code: SpanStatusCode.OK});\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\treturn result.json<Record<string, unknown>>();\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","context"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/KMicro.ts"],"sourcesContent":["export * from './KMicro.js';\n","import assert from 'node:assert';\nimport {Svc, type Service, type ServiceGroup} from '@nats-io/services';\nimport {connect, headers, type NatsConnection} from '@nats-io/transport-node';\nimport {\n\tcontext,\n\tpropagation,\n\tSpanKind,\n\tSpanStatusCode,\n\ttrace,\n\ttype Context,\n\ttype Span,\n} from '@opentelemetry/api';\nimport {OTLPTraceExporter} from '@opentelemetry/exporter-trace-otlp-proto';\nimport {Resource} from '@opentelemetry/resources';\nimport {NodeSDK} from '@opentelemetry/sdk-node';\nimport {\n\tATTR_MESSAGING_SYSTEM,\n\tATTR_RPC_METHOD,\n\tATTR_RPC_SERVICE,\n\tATTR_SERVICE_NAME,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport pino, {type Logger} from 'pino';\n\nexport async function init(\n\tnats: string,\n\tserviceName: string,\n\tversion: string,\n\tdescription?: string,\n) {\n\tconst kmicro = new Kmicro({\n\t\tname: serviceName,\n\t\tversion,\n\t\tdescription,\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 otel: NodeSDK | undefined;\n\tprivate readonly pinoLogger: pino.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) {\n\t\tthis.pinoLogger = pino.pino();\n\t}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.pinoLogger.child({module});\n\t}\n\n\tpublic async init(natsConnection: string) {\n\t\tthis.nc = await connect({\n\t\t\tname: this.meta.name,\n\t\t\tservers: natsConnection,\n\t\t});\n\t\tconst svc = new Svc(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\tthis.otel = new NodeSDK({\n\t\t\tserviceName: this.meta.name,\n\t\t\ttraceExporter: new OTLPTraceExporter(),\n\t\t\tresource: new Resource({\n\t\t\t\t[ATTR_SERVICE_NAME]: this.meta.name,\n\t\t\t\t[ATTR_MESSAGING_SYSTEM]: 'nats',\n\t\t\t}),\n\t\t});\n\n\t\tthis.otel.start();\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\tawait this.otel?.shutdown().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(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.pinoLogger.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 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\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},\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\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},\n\t): Promise<Uint8Array> {\n\t\tassert(this.nc);\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},\n\t\t\toptions,\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},\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},\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},\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},\n\toptions?: {\n\t\t/**\n\t\t * @default 5000 ms\n\t\t */\n\t\ttimeout?: number;\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 callingContext: Context = propagation.extract(\n\t\tcontext.active(),\n\t\tmeta.context ?? {},\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\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\tspan.setStatus({code: SpanStatusCode.OK});\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\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","context"]}
package/dist/index.d.cts CHANGED
@@ -4,12 +4,12 @@ import pino, { Logger } from 'pino';
4
4
 
5
5
  declare function init(nats: string, serviceName: string, version: string, description?: string): Promise<Kmicro>;
6
6
  interface Callable {
7
- call(target: string, payload: Record<string, any>, options?: {
7
+ call(target: string, payload: Uint8Array, options?: {
8
8
  /**
9
9
  * @default 5000 ms
10
10
  */
11
11
  timeout?: number;
12
- }): Promise<Record<string, unknown>>;
12
+ }): Promise<Uint8Array>;
13
13
  }
14
14
  declare class Kmicro implements Callable {
15
15
  private readonly meta;
@@ -26,16 +26,16 @@ declare class Kmicro implements Callable {
26
26
  getLogger(module?: string): pino.pino.Logger<never, boolean>;
27
27
  init(natsConnection: string): Promise<void>;
28
28
  stop(): Promise<void>;
29
- addEndpoint(name: string, handler: (context_: RequestContext, data: Record<string, any>) => Promise<Record<string, any>>): void;
29
+ addEndpoint(name: string, handler: (context_: RequestContext, data: Uint8Array) => Promise<Uint8Array>): void;
30
30
  /**
31
31
  * Start a new call
32
32
  */
33
- call(target: string, payload: Record<string, any>, options?: {
33
+ call(target: string, payload: Uint8Array, options?: {
34
34
  /**
35
35
  * @default 5000 ms
36
36
  */
37
37
  timeout?: number;
38
- }): Promise<Record<string, unknown>>;
38
+ }): Promise<Uint8Array>;
39
39
  }
40
40
  declare class RequestContext {
41
41
  readonly context: Context;
@@ -51,17 +51,17 @@ declare class RequestContext {
51
51
  currentService: string;
52
52
  });
53
53
  getLogger(module?: string): pino.pino.Logger<never, boolean>;
54
- call(target: string, payload: Record<string, any>, options?: {
54
+ call(target: string, payload: Uint8Array, options?: {
55
55
  /**
56
56
  * @default 5000 ms
57
57
  */
58
58
  timeout?: number;
59
- }): Promise<Record<string, unknown>>;
59
+ }): Promise<Uint8Array>;
60
60
  }
61
61
  declare class CallError extends Error {
62
62
  private readonly target;
63
63
  private readonly payload;
64
- constructor(message: string, target: string, payload: Record<string, unknown>);
64
+ constructor(message: string, target: string, payload: Uint8Array);
65
65
  }
66
66
 
67
67
  export { CallError, Kmicro, RequestContext, init };
package/dist/index.d.ts CHANGED
@@ -4,12 +4,12 @@ import pino, { Logger } from 'pino';
4
4
 
5
5
  declare function init(nats: string, serviceName: string, version: string, description?: string): Promise<Kmicro>;
6
6
  interface Callable {
7
- call(target: string, payload: Record<string, any>, options?: {
7
+ call(target: string, payload: Uint8Array, options?: {
8
8
  /**
9
9
  * @default 5000 ms
10
10
  */
11
11
  timeout?: number;
12
- }): Promise<Record<string, unknown>>;
12
+ }): Promise<Uint8Array>;
13
13
  }
14
14
  declare class Kmicro implements Callable {
15
15
  private readonly meta;
@@ -26,16 +26,16 @@ declare class Kmicro implements Callable {
26
26
  getLogger(module?: string): pino.pino.Logger<never, boolean>;
27
27
  init(natsConnection: string): Promise<void>;
28
28
  stop(): Promise<void>;
29
- addEndpoint(name: string, handler: (context_: RequestContext, data: Record<string, any>) => Promise<Record<string, any>>): void;
29
+ addEndpoint(name: string, handler: (context_: RequestContext, data: Uint8Array) => Promise<Uint8Array>): void;
30
30
  /**
31
31
  * Start a new call
32
32
  */
33
- call(target: string, payload: Record<string, any>, options?: {
33
+ call(target: string, payload: Uint8Array, options?: {
34
34
  /**
35
35
  * @default 5000 ms
36
36
  */
37
37
  timeout?: number;
38
- }): Promise<Record<string, unknown>>;
38
+ }): Promise<Uint8Array>;
39
39
  }
40
40
  declare class RequestContext {
41
41
  readonly context: Context;
@@ -51,17 +51,17 @@ declare class RequestContext {
51
51
  currentService: string;
52
52
  });
53
53
  getLogger(module?: string): pino.pino.Logger<never, boolean>;
54
- call(target: string, payload: Record<string, any>, options?: {
54
+ call(target: string, payload: Uint8Array, options?: {
55
55
  /**
56
56
  * @default 5000 ms
57
57
  */
58
58
  timeout?: number;
59
- }): Promise<Record<string, unknown>>;
59
+ }): Promise<Uint8Array>;
60
60
  }
61
61
  declare class CallError extends Error {
62
62
  private readonly target;
63
63
  private readonly payload;
64
- constructor(message: string, target: string, payload: Record<string, unknown>);
64
+ constructor(message: string, target: string, payload: Uint8Array);
65
65
  }
66
66
 
67
67
  export { CallError, Kmicro, RequestContext, init };
package/dist/index.js CHANGED
@@ -1,11 +1,7 @@
1
1
  // src/KMicro.ts
2
2
  import assert from "node:assert";
3
3
  import { Svc } from "@nats-io/services";
4
- import {
5
- connect,
6
- headers,
7
- JSONCodec
8
- } from "@nats-io/transport-node";
4
+ import { connect, headers } from "@nats-io/transport-node";
9
5
  import {
10
6
  context,
11
7
  propagation,
@@ -32,7 +28,6 @@ async function init(nats, serviceName, version, description) {
32
28
  await kmicro.init(nats);
33
29
  return kmicro;
34
30
  }
35
- var codec = JSONCodec();
36
31
  var Kmicro = class {
37
32
  constructor(meta) {
38
33
  this.meta = meta;
@@ -131,8 +126,8 @@ var Kmicro = class {
131
126
  currentService: this.meta.name
132
127
  }
133
128
  );
134
- const result = await handler(requestContext, message.json());
135
- message.respond(codec.encode(result));
129
+ const result = await handler(requestContext, message.data);
130
+ message.respond(result);
136
131
  span.setStatus({ code: SpanStatusCode.OK });
137
132
  } catch (error_) {
138
133
  span.recordException(error_);
@@ -228,7 +223,7 @@ async function doCall(nc, target, payload, meta, options) {
228
223
  }
229
224
  });
230
225
  try {
231
- const result = await nc.request(target, codec.encode(payload), {
226
+ const result = await nc.request(target, payload, {
232
227
  headers: natsHeadersMap,
233
228
  timeout: options?.timeout ?? 5e3
234
229
  });
@@ -242,7 +237,7 @@ async function doCall(nc, target, payload, meta, options) {
242
237
  payload
243
238
  );
244
239
  }
245
- return result.json();
240
+ return result.data;
246
241
  } finally {
247
242
  span.end();
248
243
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/KMicro.ts"],"sourcesContent":["import assert from 'node:assert';\nimport {Svc, type Service, type ServiceGroup} from '@nats-io/services';\nimport {\n\tconnect,\n\theaders,\n\tJSONCodec,\n\ttype NatsConnection,\n} from '@nats-io/transport-node';\nimport {\n\tcontext,\n\tpropagation,\n\tSpanKind,\n\tSpanStatusCode,\n\ttrace,\n\ttype Context,\n\ttype Span,\n} from '@opentelemetry/api';\nimport {OTLPTraceExporter} from '@opentelemetry/exporter-trace-otlp-proto';\nimport {Resource} from '@opentelemetry/resources';\nimport {NodeSDK} from '@opentelemetry/sdk-node';\nimport {\n\tATTR_MESSAGING_SYSTEM,\n\tATTR_RPC_METHOD,\n\tATTR_RPC_SERVICE,\n\tATTR_SERVICE_NAME,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport pino, {type Logger} from 'pino';\n\nexport async function init(\n\tnats: string,\n\tserviceName: string,\n\tversion: string,\n\tdescription?: string,\n) {\n\tconst kmicro = new Kmicro({\n\t\tname: serviceName,\n\t\tversion,\n\t\tdescription,\n\t});\n\tawait kmicro.init(nats);\n\treturn kmicro;\n}\n\nconst codec = JSONCodec(); // eslint-disable-line new-cap\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\ninterface Callable {\n\tcall(\n\t\ttarget: string,\n\t\tpayload: Record<string, any>,\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<Record<string, unknown>>;\n}\n\nexport class Kmicro implements Callable {\n\tprivate service: Service | undefined;\n\tprivate group: ServiceGroup | undefined;\n\tprivate nc: NatsConnection | undefined;\n\tprivate otel: NodeSDK | undefined;\n\tprivate readonly pinoLogger: pino.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) {\n\t\tthis.pinoLogger = pino.pino();\n\t}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.pinoLogger.child({module});\n\t}\n\n\tpublic async init(natsConnection: string) {\n\t\tthis.nc = await connect({\n\t\t\tname: this.meta.name,\n\t\t\tservers: natsConnection,\n\t\t});\n\t\tconst svc = new Svc(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\tthis.otel = new NodeSDK({\n\t\t\tserviceName: this.meta.name,\n\t\t\ttraceExporter: new OTLPTraceExporter(),\n\t\t\tresource: new Resource({\n\t\t\t\t[ATTR_SERVICE_NAME]: this.meta.name,\n\t\t\t\t[ATTR_MESSAGING_SYSTEM]: 'nats',\n\t\t\t}),\n\t\t});\n\n\t\tthis.otel.start();\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\tawait this.otel?.shutdown().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: Record<string, any>,\n\t\t) => Promise<Record<string, any>>,\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(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.pinoLogger.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 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\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},\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst result = await handler(requestContext, message.json());\n\t\t\t\t\t\tmessage.respond(codec.encode(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\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: Record<string, any>,\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<Record<string, unknown>> {\n\t\tassert(this.nc);\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},\n\t\t\toptions,\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},\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: Record<string, any>,\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<Record<string, unknown>> {\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},\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: Record<string, unknown>,\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: Record<string, any>,\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},\n\toptions?: {\n\t\t/**\n\t\t * @default 5000 ms\n\t\t */\n\t\ttimeout?: number;\n\t},\n): Promise<Record<string, unknown>> {\n\tif (meta.callDepth >= 20) {\n\t\tthrow new Error('max call depth reached: ' + meta.callDepth);\n\t}\n\n\tconst callingContext: Context = propagation.extract(\n\t\tcontext.active(),\n\t\tmeta.context ?? {},\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\n\t\t\ttry {\n\t\t\t\tconst result = await nc.request(target, codec.encode(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\tspan.setStatus({code: SpanStatusCode.OK});\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\treturn result.json<Record<string, unknown>>();\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":["context"]}
1
+ {"version":3,"sources":["../src/KMicro.ts"],"sourcesContent":["import assert from 'node:assert';\nimport {Svc, type Service, type ServiceGroup} from '@nats-io/services';\nimport {connect, headers, type NatsConnection} from '@nats-io/transport-node';\nimport {\n\tcontext,\n\tpropagation,\n\tSpanKind,\n\tSpanStatusCode,\n\ttrace,\n\ttype Context,\n\ttype Span,\n} from '@opentelemetry/api';\nimport {OTLPTraceExporter} from '@opentelemetry/exporter-trace-otlp-proto';\nimport {Resource} from '@opentelemetry/resources';\nimport {NodeSDK} from '@opentelemetry/sdk-node';\nimport {\n\tATTR_MESSAGING_SYSTEM,\n\tATTR_RPC_METHOD,\n\tATTR_RPC_SERVICE,\n\tATTR_SERVICE_NAME,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport pino, {type Logger} from 'pino';\n\nexport async function init(\n\tnats: string,\n\tserviceName: string,\n\tversion: string,\n\tdescription?: string,\n) {\n\tconst kmicro = new Kmicro({\n\t\tname: serviceName,\n\t\tversion,\n\t\tdescription,\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 otel: NodeSDK | undefined;\n\tprivate readonly pinoLogger: pino.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) {\n\t\tthis.pinoLogger = pino.pino();\n\t}\n\n\tpublic getLogger(module?: string) {\n\t\treturn this.pinoLogger.child({module});\n\t}\n\n\tpublic async init(natsConnection: string) {\n\t\tthis.nc = await connect({\n\t\t\tname: this.meta.name,\n\t\t\tservers: natsConnection,\n\t\t});\n\t\tconst svc = new Svc(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\tthis.otel = new NodeSDK({\n\t\t\tserviceName: this.meta.name,\n\t\t\ttraceExporter: new OTLPTraceExporter(),\n\t\t\tresource: new Resource({\n\t\t\t\t[ATTR_SERVICE_NAME]: this.meta.name,\n\t\t\t\t[ATTR_MESSAGING_SYSTEM]: 'nats',\n\t\t\t}),\n\t\t});\n\n\t\tthis.otel.start();\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\tawait this.otel?.shutdown().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(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.pinoLogger.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 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\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},\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\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},\n\t): Promise<Uint8Array> {\n\t\tassert(this.nc);\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},\n\t\t\toptions,\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},\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},\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},\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},\n\toptions?: {\n\t\t/**\n\t\t * @default 5000 ms\n\t\t */\n\t\ttimeout?: number;\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 callingContext: Context = propagation.extract(\n\t\tcontext.active(),\n\t\tmeta.context ?? {},\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\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\tspan.setStatus({code: SpanStatusCode.OK});\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\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":";AAAA,OAAO,YAAY;AACnB,SAAQ,WAA2C;AACnD,SAAQ,SAAS,eAAmC;AACpD;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGM;AACP,SAAQ,yBAAwB;AAChC,SAAQ,gBAAe;AACvB,SAAQ,eAAc;AACtB;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,OAAO,UAAyB;AAEhC,eAAsB,KACrB,MACA,aACA,SACA,aACC;AACD,QAAM,SAAS,IAAI,OAAO;AAAA,IACzB,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACD,CAAC;AACD,QAAM,OAAO,KAAK,IAAI;AACtB,SAAO;AACR;AAgBO,IAAM,SAAN,MAAiC;AAAA,EAOvC,YACkB,MAKhB;AALgB;AAMjB,SAAK,aAAa,KAAK,KAAK;AAAA,EAC7B;AAAA,EAdQ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACS;AAAA,EAYV,UAAU,QAAiB;AACjC,WAAO,KAAK,WAAW,MAAM,EAAC,OAAM,CAAC;AAAA,EACtC;AAAA,EAEA,MAAa,KAAK,gBAAwB;AACzC,SAAK,KAAK,MAAM,QAAQ;AAAA,MACvB,MAAM,KAAK,KAAK;AAAA,MAChB,SAAS;AAAA,IACV,CAAC;AACD,UAAM,MAAM,IAAI,IAAI,KAAK,EAAE;AAC3B,SAAK,UAAU,MAAM,IAAI,IAAI;AAAA,MAC5B,MAAM,KAAK,KAAK;AAAA,MAChB,SAAS,KAAK,KAAK;AAAA,MACnB,aAAa,KAAK,KAAK;AAAA,IACxB,CAAC;AACD,SAAK,QAAQ,KAAK,QAAQ,SAAS,KAAK,KAAK,IAAI;AACjD,SAAK,OAAO,IAAI,QAAQ;AAAA,MACvB,aAAa,KAAK,KAAK;AAAA,MACvB,eAAe,IAAI,kBAAkB;AAAA,MACrC,UAAU,IAAI,SAAS;AAAA,QACtB,CAAC,iBAAiB,GAAG,KAAK,KAAK;AAAA,QAC/B,CAAC,qBAAqB,GAAG;AAAA,MAC1B,CAAC;AAAA,IACF,CAAC;AAED,SAAK,KAAK,MAAM;AAAA,EACjB;AAAA,EAEA,MAAa,OAAO;AACnB,UAAM,KAAK,SAAS,KAAK,EAAE,MAAM,CAAC,UAAmB;AACpD,cAAQ,MAAM,KAAK;AAAA,IACpB,CAAC;AACD,UAAM,KAAK,IAAI,MAAM,EAAE,MAAM,CAAC,UAAmB;AAChD,cAAQ,MAAM,KAAK;AAAA,IACpB,CAAC;AACD,UAAM,KAAK,MAAM,SAAS,EAAE,MAAM,CAAC,UAAmB;AACrD,cAAQ,MAAM,KAAK;AAAA,IACpB,CAAC;AAAA,EACF;AAAA,EAEO,YACN,MACA,SAIC;AACD,WAAO,KAAK,KAAK;AAEjB,SAAK,MAAM,YAAY,MAAM,OAAO,OAAO,YAAY;AACtD,aAAO,KAAK,EAAE;AACd,UAAI,OAAO;AACV,gBAAQ,MAAM,KAAK;AACnB;AAAA,MACD;AAGA,YAAM,mBAAmB,OAAO;AAAA,QAC/B,QAAQ,SAAS,IAAI,WAAW,KAAK;AAAA,QACrC;AAAA,MACD;AACA,UAAI,oBAAoB,IAAI;AAC3B,cAAM,IAAI,MAAM,6BAA6B,gBAAgB;AAAA,MAC9D;AAEA,YAAM,kBAA2B,YAAY;AAAA,QAC5C,QAAQ,OAAO;AAAA,QACf,QAAQ;AAAA,QACR;AAAA,UACC,IAAI,SAAS,KAAK;AACjB,mBAAO,SAAS,IAAI,GAAG;AAAA,UACxB;AAAA,UACA,KAAK,SAAS;AACb,mBAAO,SAAS,KAAK,KAAK,CAAC;AAAA,UAC5B;AAAA,QACD;AAAA,MACD;AAEA,YAAM,SAAS,MAAM,UAAU,MAAM,KAAK,KAAK,OAAO;AACtD,YAAM,WAAW,WAAW,KAAK,KAAK,IAAI,IAAI,IAAI;AAClD,YAAM,OAAO;AAAA,QACZ;AAAA,QACA;AAAA,UACC,MAAM,SAAS;AAAA,QAChB;AAAA,QACA;AAAA,QACA,OAAO,SAAS;AACf,gBAAM,aAAa,KAAK,WAAW,MAAM;AAAA,YACxC,QAAQ;AAAA,YACR,QAAQ,KAAK,YAAY,EAAE;AAAA,YAC3B,SAAS,KAAK,YAAY,EAAE;AAAA,UAC7B,CAAC;AACD,cAAI;AACH,kBAAM,iBAAiB,IAAI;AAAA,cAC1B;AAAA,cACA;AAAA,cACA,KAAK;AAAA,cACL;AAAA,cACA;AAAA,gBACC,WAAW;AAAA,gBACX,gBAAgB,KAAK,KAAK;AAAA,cAC3B;AAAA,YACD;AACA,kBAAM,SAAS,MAAM,QAAQ,gBAAgB,QAAQ,IAAI;AACzD,oBAAQ,QAAQ,MAAM;AACtB,iBAAK,UAAU,EAAC,MAAM,eAAe,GAAE,CAAC;AAAA,UACzC,SAAS,QAAQ;AAChB,iBAAK,gBAAgB,MAAe;AACpC,oBAAQ,aAAa,KAAM,OAAiB,OAAO;AACnD,iBAAK,UAAU,EAAC,MAAM,eAAe,MAAK,CAAC;AAAA,UAC5C,UAAE;AACD,iBAAK,IAAI;AAAA,UACV;AAAA,QACD;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,KACZ,QACA,SACA,SAMsB;AACtB,WAAO,KAAK,EAAE;AACd,WAAO;AAAA,MACN,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,QACC,WAAW;AAAA,QACX,SAAS;AAAA,QACT,gBAAgB,KAAK,KAAK;AAAA,MAC3B;AAAA,MACA;AAAA,IACD;AAAA,EACD;AACD;AAEO,IAAM,iBAAN,MAAqB;AAAA;AAAA,EAE3B,YACUA,UACA,MACA,IACQ,QACR,MAIR;AARQ,mBAAAA;AACA;AACA;AACQ;AACR;AAAA,EAIP;AAAA,EAEI,UAAU,QAAiB;AACjC,WAAO,KAAK,OAAO,MAAM;AAAA,MACxB;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEA,MAAa,KACZ,QACA,SACA,SAMsB;AACtB,WAAO;AAAA,MACN,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,QACC,WAAW,KAAK,KAAK;AAAA,QACrB,SAAS,KAAK;AAAA,QACd,gBAAgB,KAAK,KAAK;AAAA,MAC3B;AAAA,MACA;AAAA,IACD;AAAA,EACD;AACD;AAEO,IAAM,YAAN,cAAwB,MAAM;AAAA,EACpC,YACC,SACiB,QACA,SAChB;AACD,UAAM,OAAO;AAHI;AACA;AAGjB,SAAK,OAAO;AAAA,EACb;AACD;AAGA,eAAe,OACd,IACA,QACA,SACA,MAQA,SAMsB;AACtB,MAAI,KAAK,aAAa,IAAI;AACzB,UAAM,IAAI,MAAM,6BAA6B,KAAK,SAAS;AAAA,EAC5D;AAEA,QAAM,iBAA0B,YAAY;AAAA,IAC3C,QAAQ,OAAO;AAAA,IACf,KAAK,WAAW,CAAC;AAAA,EAClB;AACA,QAAM,SAAS,MAAM,UAAU,SAAS;AACxC,QAAM,CAAC,SAAS,MAAM,IAAI,OAAO,MAAM,GAAG;AAC1C,SAAO,OAAO;AAAA,IACb,SAAS,MAAM;AAAA,IACf;AAAA,MACC,MAAM,SAAS;AAAA,MACf,YAAY;AAAA,QACX,CAAC,gBAAgB,GAAG;AAAA,QACpB,CAAC,eAAe,GAAG;AAAA,MACpB;AAAA,IACD;AAAA,IACA;AAAA,IACA,OAAO,SAAS;AAEf,YAAM,iBAAiB,QAAQ;AAC/B,qBAAe,IAAI,cAAc,KAAK,YAAY,GAAG,QAAQ,CAAC,CAAC;AAC/D,kBAAY,OAAO,QAAQ,OAAO,GAAG,gBAAgB;AAAA,QACpD,IAAI,SAAS,KAAK,OAAO;AACxB,kBAAQ,IAAI,KAAK,KAAK;AAAA,QACvB;AAAA,MACD,CAAC;AAED,UAAI;AACH,cAAM,SAAS,MAAM,GAAG,QAAQ,QAAQ,SAAS;AAAA,UAChD,SAAS;AAAA,UACT,SAAS,SAAS,WAAW;AAAA,QAC9B,CAAC;AACD,aAAK,UAAU,EAAC,MAAM,eAAe,GAAE,CAAC;AACxC,YAAI,OAAO,SAAS,IAAI,yBAAyB,GAAG;AACnD,eAAK,UAAU,EAAC,MAAM,eAAe,MAAK,CAAC;AAC3C,eAAK,gBAAgB,OAAO,QAAQ,IAAI,oBAAoB,CAAC;AAC7D,gBAAM,IAAI;AAAA,YACT,qBAAqB,OAAO,QAAQ,IAAI,oBAAoB;AAAA,YAC5D;AAAA,YACA;AAAA,UACD;AAAA,QACD;AAEA,eAAO,OAAO;AAAA,MACf,UAAE;AACD,aAAK,IAAI;AAAA,MACV;AAAA,IACD;AAAA,EACD;AACD;","names":["context"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kultify/kmicro-js",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",