unnbound-events 1.0.19 → 1.0.21

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.
@@ -1,73 +1,60 @@
1
1
  export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
2
2
  export interface EventRequest<Body = unknown, Query = Record<string, unknown>> {
3
- method: HttpMethod;
4
- path: string;
5
- headers: Record<string, string>;
6
- query: Query;
7
- body: Body;
8
- metadata?: Record<string, unknown>;
3
+ method: HttpMethod;
4
+ path: string;
5
+ headers: Record<string, string>;
6
+ query: Query;
7
+ body: Body;
8
+ metadata?: Record<string, unknown>;
9
9
  }
10
10
  export interface EventResponse<Body = unknown> {
11
- status: number;
12
- headers?: Record<string, string>;
13
- body?: Body;
11
+ status: number;
12
+ headers?: Record<string, string>;
13
+ body?: Body;
14
14
  }
15
- export type RouteHandler<ReqBody = unknown, ResBody = unknown> = (request: EventRequest<ReqBody>) => Promise<EventResponse<ResBody>> | EventResponse<ResBody>;
15
+ export type RouteHandler<ReqBody = unknown, ResBody = unknown> = (
16
+ request: EventRequest<ReqBody>
17
+ ) => Promise<EventResponse<ResBody>> | EventResponse<ResBody>;
16
18
  export type RouteMatcher = string | RegExp | ((path: string) => boolean);
17
19
  export interface RegisteredRoute {
18
- method: HttpMethod;
19
- matcher: RouteMatcher;
20
- handler: RouteHandler<any, any>;
20
+ method: HttpMethod;
21
+ matcher: RouteMatcher;
22
+ handler: RouteHandler<any, any>;
21
23
  }
22
24
  export type SqsRecord = {
23
- messageId: string;
24
- body: string;
25
+ messageId: string;
26
+ body: string;
25
27
  };
26
28
  export interface SqsBatchEvent {
27
- Records: SqsRecord[];
28
- }
29
- export interface StartOptions {
30
- http?: {
31
- port?: number;
32
- };
33
- sqs?: {
34
- queueUrl?: string;
35
- region?: string;
36
- waitTimeSeconds?: number;
37
- maxMessages?: number;
38
- visibilityTimeoutSeconds?: number;
39
- };
29
+ Records: SqsRecord[];
40
30
  }
41
31
  export interface EventsClient {
42
- on: (method: HttpMethod, matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
43
- handle: (request: EventRequest<any>) => Promise<EventResponse<any>>;
44
- get: (matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
45
- post: (matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
46
- put: (matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
47
- patch: (matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
48
- delete: (matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
49
- options: (matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
50
- head: (matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
51
- http: (options?: {
52
- port?: number;
53
- }) => Promise<{
54
- close: () => Promise<void>;
55
- }>;
56
- sqs: () => (event: SqsBatchEvent) => Promise<{
57
- successes: number;
58
- failures: Array<{
59
- messageId: string;
60
- reason: string;
61
- }>;
62
- }>;
63
- sqsListen: (options?: {
64
- queueUrl?: string;
65
- region?: string;
66
- waitTimeSeconds?: number;
67
- maxMessages?: number;
68
- visibilityTimeoutSeconds?: number;
69
- }) => Promise<{
70
- stop: () => Promise<void>;
32
+ on: (method: HttpMethod, matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
33
+ handle: (request: EventRequest<any>) => Promise<EventResponse<any>>;
34
+ get: (matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
35
+ post: (matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
36
+ put: (matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
37
+ patch: (matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
38
+ delete: (matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
39
+ options: (matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
40
+ head: (matcher: RouteMatcher, handler: RouteHandler<any, any>) => void;
41
+ http: (options?: { port?: number }) => Promise<{
42
+ close: () => Promise<void>;
43
+ }>;
44
+ sqs: () => (event: SqsBatchEvent) => Promise<{
45
+ successes: number;
46
+ failures: Array<{
47
+ messageId: string;
48
+ reason: string;
71
49
  }>;
72
- start: (options?: StartOptions) => Promise<void>;
50
+ }>;
51
+ sqsListen: (options?: {
52
+ queueUrl?: string;
53
+ region?: string;
54
+ waitTimeSeconds?: number;
55
+ maxMessages?: number;
56
+ visibilityTimeoutSeconds?: number;
57
+ }) => Promise<{
58
+ stop: () => Promise<void>;
59
+ }>;
73
60
  }
@@ -1,2 +1,2 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ 'use strict';
2
+ Object.defineProperty(exports, '__esModule', { value: true });
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.defaultIgnoreTraceRoutes = exports.shouldIgnorePath = void 0;
4
7
  exports.createEventsClient = createEventsClient;
5
8
  const unnbound_logger_sdk_1 = require("unnbound-logger-sdk");
6
- const http = (() => {
7
- try {
8
- return (require && require('http'));
9
- }
10
- catch {
11
- return null;
12
- }
13
- })();
9
+ const internal_1 = require("unnbound-logger-sdk/dist/internal");
10
+ const types_1 = require("unnbound-logger-sdk/dist/types");
11
+ const axios_1 = __importDefault(require("axios"));
12
+ const logger = unnbound_logger_sdk_1.logger.child((0, internal_1.internal)());
13
+ const http = require('http');
14
14
  function matchPath(matcher, path) {
15
15
  if (typeof matcher === 'string') {
16
16
  return matcher === path;
@@ -23,15 +23,13 @@ function matchPath(matcher, path) {
23
23
  function isMiddleware(value) {
24
24
  return typeof value === 'function' && value.length >= 2;
25
25
  }
26
- const TRACE_HEADER_KEY = 'x-unnbound-trace-id';
27
- const MESSAGE_HEADER_KEY = 'x-message-id';
28
26
  const getHeaderValue = (headers, name) => {
29
27
  const needle = name.toLowerCase();
30
28
  for (const [key, value] of Object.entries(headers)) {
31
29
  if (key.toLowerCase() === needle)
32
30
  return value;
33
31
  }
34
- return undefined;
32
+ return;
35
33
  };
36
34
  const shouldIgnorePath = (path, patterns) => {
37
35
  return patterns.some((pattern) => {
@@ -77,24 +75,14 @@ async function fetchS3Payload(s3Client, bucket, key, versionId) {
77
75
  return buffer.toString('utf-8');
78
76
  }
79
77
  catch (error) {
80
- const err = error instanceof Error ? error : new Error(String(error));
81
- unnbound_logger_sdk_1.logger.error({ err, bucket, key }, 'Failed to fetch S3 payload');
82
- throw new Error(`Failed to fetch S3 payload: ${err.message}`);
78
+ const message = error instanceof Error ? error.message : String(error);
79
+ logger.error({ err: error, bucket, key }, 'Failed to fetch S3 payload');
80
+ throw new Error(`Failed to fetch S3 payload: ${message}`);
83
81
  }
84
82
  }
85
83
  // Helper function to decompress payload
86
84
  async function decompressPayload(compressed, compressionType) {
87
- const zlib = (() => {
88
- try {
89
- return require('zlib');
90
- }
91
- catch {
92
- return null;
93
- }
94
- })();
95
- if (!zlib) {
96
- throw new Error('zlib is required for decompression');
97
- }
85
+ const zlib = require('zlib');
98
86
  return new Promise((resolve, reject) => {
99
87
  const buffer = Buffer.from(compressed);
100
88
  const callback = (err, result) => {
@@ -116,6 +104,11 @@ async function decompressPayload(compressed, compressionType) {
116
104
  }
117
105
  });
118
106
  }
107
+ const getWorkspaceId = () => process.env.UNNBOUND_WORKFLOW_URL.replace(/^https?:\/\//, '').replace(/\.unnbound\.ai$/, '');
108
+ const getEnvironment = () => process.env.UNNBOUND_WORKFLOW_URL.includes('stg.unnbound.ai') ? 'stg' : 'prod';
109
+ const getWorkflowDomain = () => {
110
+ return getEnvironment() === 'stg' ? 'workflow.stg.unnbound.ai' : 'workflow.unnbound.ai';
111
+ };
119
112
  function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes) {
120
113
  const routes = [];
121
114
  const middlewares = [];
@@ -133,12 +126,12 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
133
126
  }
134
127
  const metadataTraceId = typeof request.metadata?.traceId === 'string' ? request.metadata.traceId : undefined;
135
128
  const metadataMessageId = typeof request.metadata?.messageId === 'string' ? request.metadata.messageId : undefined;
136
- const headerMessageId = getHeaderValue(request.headers, MESSAGE_HEADER_KEY);
129
+ const headerMessageId = getHeaderValue(request.headers, types_1.defaultTraceHeaderKey);
137
130
  if (metadataMessageId && headerMessageId && metadataMessageId !== headerMessageId) {
138
- unnbound_logger_sdk_1.logger.warn({ metadataMessageId, headerMessageId }, 'Message ID mismatch detected; defaulting to header value.');
131
+ logger.warn({ metadataMessageId, headerMessageId }, 'Message ID mismatch detected; defaulting to header value.');
139
132
  }
140
133
  const messageId = headerMessageId ?? metadataMessageId;
141
- const headerTraceId = getHeaderValue(request.headers, TRACE_HEADER_KEY);
134
+ const headerTraceId = getHeaderValue(request.headers, types_1.defaultMessageHeaderKey);
142
135
  const traceId = metadataTraceId ?? headerTraceId;
143
136
  const context = traceId || messageId
144
137
  ? {
@@ -184,6 +177,7 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
184
177
  });
185
178
  };
186
179
  middlewares.push({ fn: requestLoggerMiddleware });
180
+ const enqueueClient = (0, unnbound_logger_sdk_1.traceAxios)(axios_1.default.create({ baseURL: `https://${getWorkflowDomain()}/async/${getWorkspaceId()}` }), { getPayload: internal_1.internal });
187
181
  return {
188
182
  on(method, matcher, handler) {
189
183
  routes.push({ method, matcher, handler });
@@ -241,8 +235,7 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
241
235
  return response;
242
236
  }
243
237
  catch (error) {
244
- const err = error instanceof Error ? error : new Error(String(error));
245
- unnbound_logger_sdk_1.logger.error({ err, path: request.path }, 'Handler error');
238
+ logger.error({ err: error, path: request.path }, 'Handler error');
246
239
  return { status: 500, body: { message: 'Internal Server Error' } };
247
240
  }
248
241
  },
@@ -308,7 +301,7 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
308
301
  });
309
302
  });
310
303
  await new Promise((resolve) => server.listen(port, resolve));
311
- unnbound_logger_sdk_1.logger.info({ port }, 'HTTP server started');
304
+ logger.info({ port }, 'HTTP server started');
312
305
  return {
313
306
  close() {
314
307
  return new Promise((resolve, reject) => {
@@ -350,7 +343,7 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
350
343
  if (!s3Client) {
351
344
  throw new Error('S3 client not initialized but S3 pointer message received');
352
345
  }
353
- unnbound_logger_sdk_1.logger.info({ bucket: pointer.s3BucketName, key: pointer.s3Key }, 'Fetching S3 pointer payload');
346
+ logger.info({ bucket: pointer.s3BucketName, key: pointer.s3Key }, 'Fetching S3 pointer payload');
354
347
  recordBody = await fetchS3Payload(s3Client, pointer.s3BucketName, pointer.s3Key);
355
348
  envelope = JSON.parse(recordBody);
356
349
  }
@@ -359,8 +352,7 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
359
352
  }
360
353
  }
361
354
  catch (error) {
362
- const err = error instanceof Error ? error : new Error(String(error));
363
- unnbound_logger_sdk_1.logger.error({ err }, 'Failed to parse SQS record body');
355
+ logger.error({ err: error }, 'Failed to parse SQS record body');
364
356
  throw error;
365
357
  }
366
358
  // Check if envelope payload is stored in S3
@@ -372,7 +364,7 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
372
364
  if (!s3Client) {
373
365
  throw new Error('S3 client not initialized but S3 payload message received');
374
366
  }
375
- unnbound_logger_sdk_1.logger.info({
367
+ logger.info({
376
368
  type: envelope.payload.type,
377
369
  bucket: envelope.payload.location.bucket,
378
370
  key: envelope.payload.location.key,
@@ -380,7 +372,7 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
380
372
  let payloadData = await fetchS3Payload(s3Client, envelope.payload.location.bucket, envelope.payload.location.key, envelope.payload.location.versionId);
381
373
  // Handle decompression if needed
382
374
  if (envelope.payload.compressed && envelope.payload.compressionType) {
383
- unnbound_logger_sdk_1.logger.info({ compressionType: envelope.payload.compressionType }, 'Decompressing payload');
375
+ logger.info({ compressionType: envelope.payload.compressionType }, 'Decompressing payload');
384
376
  payloadData = await decompressPayload(new TextEncoder().encode(payloadData), envelope.payload.compressionType);
385
377
  }
386
378
  // Parse the payload and set it as the request body
@@ -392,14 +384,14 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
392
384
  }
393
385
  }
394
386
  // Continue with standard envelope processing
395
- const headerMessageId = getHeaderValue(envelope.request.headers, MESSAGE_HEADER_KEY);
387
+ const headerMessageId = getHeaderValue(envelope.request.headers, types_1.defaultMessageHeaderKey);
396
388
  const envelopeMessageId = typeof envelope.metadata?.messageId === 'string'
397
389
  ? envelope.metadata.messageId
398
390
  : typeof envelope.messageId === 'string'
399
391
  ? envelope.messageId
400
392
  : undefined;
401
393
  if (envelopeMessageId && headerMessageId && envelopeMessageId !== headerMessageId) {
402
- unnbound_logger_sdk_1.logger.warn({ envelopeMessageId, headerMessageId }, 'Message ID mismatch detected in SQS envelope; defaulting to header value.');
394
+ logger.warn({ envelopeMessageId, headerMessageId }, 'Message ID mismatch detected in SQS envelope; defaulting to header value.');
403
395
  }
404
396
  const messageId = headerMessageId ?? envelopeMessageId ?? record.messageId ?? undefined;
405
397
  const originalMessageId = envelopeMessageId && envelopeMessageId !== messageId
@@ -447,10 +439,10 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
447
439
  }, traceContext);
448
440
  }
449
441
  catch (error) {
450
- const err = error instanceof Error ? error : new Error(String(error));
442
+ const reason = error instanceof Error ? error.message : String(error);
451
443
  failures.push({
452
444
  messageId: record.messageId,
453
- reason: err.message ?? 'Unknown error',
445
+ reason: reason ?? 'Unknown error',
454
446
  });
455
447
  }
456
448
  }));
@@ -465,38 +457,27 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
465
457
  if (bucketName || options?.s3) {
466
458
  s3Options = options?.s3 || {};
467
459
  if (!bucketName) {
468
- unnbound_logger_sdk_1.logger.warn('S3 options provided but no bucket name specified. S3 payload support disabled.');
460
+ logger.error('S3 options provided but no bucket name specified. S3 payload support disabled.');
469
461
  }
470
462
  else {
471
463
  try {
472
464
  s3Client = createS3Client({ ...s3Options, bucketName });
473
- unnbound_logger_sdk_1.logger.info({ bucket: bucketName }, 'S3 client initialized for payload offloading');
465
+ logger.info({ bucket: bucketName }, 'S3 client initialized for payload offloading');
474
466
  }
475
467
  catch (error) {
476
- const err = error instanceof Error ? error : new Error(String(error));
477
- unnbound_logger_sdk_1.logger.error({ err }, 'Failed to initialize S3 client');
468
+ logger.error({ err: error }, 'Failed to initialize S3 client');
478
469
  throw error;
479
470
  }
480
471
  }
481
472
  }
482
- const awsSqs = (() => {
483
- try {
484
- return require('@aws-sdk/client-sqs');
485
- }
486
- catch {
487
- return null;
488
- }
489
- })();
490
- if (!awsSqs) {
491
- throw new Error('@aws-sdk/client-sqs is required to use sqsListen');
492
- }
473
+ const awsSqs = require('@aws-sdk/client-sqs');
493
474
  const queueUrl = options?.queueUrl || env.UNNBOUND_SQS_QUEUE_URL || env.SQS_QUEUE_URL || env.QUEUE_URL;
494
475
  if (!queueUrl || queueUrl === undefined) {
495
476
  throw new Error('SQS queue URL not provided. Set UNNBOUND_SQS_QUEUE_URL, SQS_QUEUE_URL env or pass options.queueUrl');
496
477
  }
497
478
  const region = options?.region || env.AWS_REGION || 'us-east-1';
498
479
  const endpoint = env.AWS_SQS_ENDPOINT || env.AWS_ENDPOINT_URL || undefined;
499
- const waitTimeSeconds = options?.waitTimeSeconds ?? 10;
480
+ const waitTimeSeconds = options?.waitTimeSeconds ?? 20;
500
481
  const maxMessages = options?.maxMessages ?? 10;
501
482
  const visibilityTimeout = options?.visibilityTimeoutSeconds;
502
483
  const sqs = new awsSqs.SQSClient({ region, endpoint });
@@ -534,7 +515,7 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
534
515
  }
535
516
  }
536
517
  catch (err) {
537
- unnbound_logger_sdk_1.logger.error({ err }, 'SQS listen loop error');
518
+ logger.error({ err }, 'SQS listen loop error');
538
519
  }
539
520
  }
540
521
  }
@@ -544,12 +525,12 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
544
525
  return new Promise((resolve, reject) => {
545
526
  const testConnection = async () => {
546
527
  try {
547
- const testParams = {
528
+ const command = new awsSqs.ReceiveMessageCommand({
548
529
  QueueUrl: queueUrl,
549
530
  MaxNumberOfMessages: 1,
550
- WaitTimeSeconds: 0, // Don't wait, just test connection
551
- };
552
- await sqs.send(new awsSqs.ReceiveMessageCommand(testParams));
531
+ WaitTimeSeconds: 0,
532
+ });
533
+ await sqs.send(command);
553
534
  resolve({
554
535
  stop() {
555
536
  stopped = true;
@@ -558,7 +539,7 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
558
539
  });
559
540
  }
560
541
  catch (error) {
561
- unnbound_logger_sdk_1.logger.error({ err: error, queueUrl: queueUrl.replace(/\/[^/]+$/, '/***') }, 'SQS connection test failed');
542
+ logger.error({ err: error, queueUrl: queueUrl.replace(/\/[^/]+$/, '/***') }, 'SQS connection test failed');
562
543
  reject(error instanceof Error ? error : new Error(String(error)));
563
544
  }
564
545
  };
@@ -566,6 +547,29 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
566
547
  setTimeout(testConnection, 100);
567
548
  });
568
549
  },
550
+ async enqueue(event) {
551
+ if (!event.path.startsWith('/'))
552
+ throw new Error('Path must be relative.');
553
+ const config = {
554
+ headers: {
555
+ ...event.headers,
556
+ [types_1.defaultTraceHeaderKey]: event.metadata?.traceId,
557
+ [types_1.defaultMessageHeaderKey]: event.metadata?.messageId,
558
+ },
559
+ params: event.query,
560
+ };
561
+ const method = event.method.toLowerCase();
562
+ switch (method) {
563
+ case 'get':
564
+ case 'delete':
565
+ return await enqueueClient[method](event.path, config).then(() => void 0);
566
+ case 'post':
567
+ case 'put':
568
+ case 'patch':
569
+ return await enqueueClient[method](event.path, event.body, config).then(() => void 0);
570
+ }
571
+ throw new Error(`Unsupported method: ${event.method}`);
572
+ },
569
573
  async start(options) {
570
574
  // Default to starting both HTTP and SQS if no options provided
571
575
  const httpOptions = options?.http ?? { port: 3000 };
@@ -578,7 +582,7 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
578
582
  httpServer = await this.http(httpOptions);
579
583
  }
580
584
  catch (error) {
581
- unnbound_logger_sdk_1.logger.warn({ error }, 'Failed to start HTTP server, continuing without it');
585
+ logger.error({ err: error }, 'Failed to start HTTP server, continuing without it');
582
586
  }
583
587
  // Start SQS listener
584
588
  let sqsListener;
@@ -586,7 +590,7 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
586
590
  sqsListener = await this.sqsListen(sqsListenOptions);
587
591
  }
588
592
  catch (error) {
589
- unnbound_logger_sdk_1.logger.warn({ error }, 'Failed to start SQS listener, continuing without it');
593
+ logger.error({ err: error }, 'Failed to start SQS listener, continuing without it');
590
594
  }
591
595
  // If neither HTTP nor SQS started successfully, throw an error
592
596
  if (!httpServer && !sqsListener) {
@@ -595,14 +599,14 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
595
599
  // Set up graceful shutdown
596
600
  const g = globalThis;
597
601
  const shutdown = async () => {
598
- unnbound_logger_sdk_1.logger.info('Received shutdown signal, closing servers...');
602
+ logger.info('Received shutdown signal, closing servers...');
599
603
  const promises = [];
600
604
  if (httpServer)
601
605
  promises.push(httpServer.close());
602
606
  if (sqsListener)
603
607
  promises.push(sqsListener.stop());
604
608
  await Promise.all(promises);
605
- unnbound_logger_sdk_1.logger.info('All servers closed');
609
+ logger.info('All servers closed');
606
610
  g.process?.exit?.(0);
607
611
  };
608
612
  // Handle SIGINT and SIGTERM
@@ -614,7 +618,7 @@ function createEventsClient(ignoreTraceRoutes = exports.defaultIgnoreTraceRoutes
614
618
  services.push(`HTTP on port ${httpOptions?.port ?? 3000}`);
615
619
  if (sqsListener)
616
620
  services.push('SQS listener');
617
- unnbound_logger_sdk_1.logger.info({ services: services.join(' and ') }, 'Services started. Press Ctrl+C to stop.');
621
+ logger.info({ services: services.join(' and ') }, 'Services started. Press Ctrl+C to stop.');
618
622
  },
619
623
  };
620
624
  }
@@ -87,4 +87,5 @@ export interface EventsClient {
87
87
  stop: () => Promise<void>;
88
88
  }>;
89
89
  start: (options?: StartOptions) => Promise<void>;
90
+ enqueue(event: EventRequest<any>): Promise<void>;
90
91
  }
@@ -1,11 +1,12 @@
1
- import { Axios, type AxiosRequestConfig, type AxiosResponse } from 'axios';
1
+ import { Axios } from 'axios';
2
2
  import { HttpOptions } from './types';
3
- type GetPayload = (config: AxiosRequestConfig, res?: AxiosResponse) => object;
4
3
  /**
5
4
  * Wraps an axios instance to add tracing and span tracking
6
5
  * @param axios - The axios instance to wrap
7
6
  * @param options - Configuration options for HTTP tracing
8
7
  * @returns The wrapped axios instance with span tracking
9
8
  */
10
- export declare const traceAxios: (client: Axios, { ignoreTraceRoutes, traceHeaderKey, getPayload, }?: HttpOptions<GetPayload>) => Axios;
11
- export {};
9
+ export declare const traceAxios: (
10
+ client: Axios,
11
+ { ignoreTraceRoutes, traceHeaderKey }?: HttpOptions
12
+ ) => Axios;
@@ -1,79 +1,85 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ 'use strict';
2
+ Object.defineProperty(exports, '__esModule', { value: true });
3
3
  exports.traceAxios = void 0;
4
- const axios_1 = require("axios");
5
- const types_1 = require("./types");
6
- const storage_1 = require("./storage");
7
- const utils_1 = require("./utils");
8
- const span_1 = require("./span");
4
+ const axios_1 = require('axios');
5
+ const types_1 = require('./types');
6
+ const storage_1 = require('./storage');
7
+ const utils_1 = require('./utils');
8
+ const span_1 = require('./span');
9
9
  const buildOutgoingHttpPayload = (config, res) => ({
10
- type: 'http',
11
- http: {
12
- url: [config.baseURL, config.url].filter(Boolean).join(''),
13
- method: config.method?.toLowerCase() ?? 'get',
14
- incoming: false,
15
- request: {
16
- headers: config.headers,
17
- body: (0, utils_1.safeJsonParse)(config.data),
18
- },
19
- response: res
20
- ? {
21
- headers: res?.headers,
22
- status: res.status,
23
- body: (0, utils_1.safeJsonParse)(res.data),
24
- }
25
- : undefined,
10
+ type: 'http',
11
+ http: {
12
+ url: [config.baseURL, config.url].filter(Boolean).join(''),
13
+ method: config.method?.toLowerCase() ?? 'get',
14
+ incoming: false,
15
+ request: {
16
+ headers: config.headers,
17
+ body: (0, utils_1.safeJsonParse)(config.data),
26
18
  },
19
+ response: res
20
+ ? {
21
+ headers: res?.headers,
22
+ status: res.status,
23
+ body: (0, utils_1.safeJsonParse)(res.data),
24
+ }
25
+ : undefined,
26
+ },
27
27
  });
28
- const getNoopPayload = () => ({});
29
28
  /**
30
29
  * Wraps an axios instance to add tracing and span tracking
31
30
  * @param axios - The axios instance to wrap
32
31
  * @param options - Configuration options for HTTP tracing
33
32
  * @returns The wrapped axios instance with span tracking
34
33
  */
35
- const traceAxios = (client, { ignoreTraceRoutes = types_1.defaultIgnoreTraceRoutes, traceHeaderKey = types_1.defaultTraceHeaderKey, getPayload = getNoopPayload, } = {
34
+ const traceAxios = (
35
+ client,
36
+ {
37
+ ignoreTraceRoutes = types_1.defaultIgnoreTraceRoutes,
38
+ traceHeaderKey = types_1.defaultTraceHeaderKey,
39
+ } = {
36
40
  ignoreTraceRoutes: types_1.defaultIgnoreTraceRoutes,
37
41
  traceHeaderKey: types_1.defaultTraceHeaderKey,
38
- getPayload: getNoopPayload,
39
- }) => {
40
- const createSpanWrappedRequest = (originalMethod, method) => {
41
- const { headers: defaultHeaders, ...partialDefaultConfig } = client.defaults;
42
- const headers = { ...defaultHeaders.common, ...(method && defaultHeaders[method]) };
43
- const defaultConfig = { ...partialDefaultConfig, headers };
44
- return async (config) => {
45
- config = (0, axios_1.mergeConfig)(defaultConfig, config);
46
- // Determine the actual config and URL
47
- const url = [config.baseURL, config.url].filter(Boolean).join('');
48
- // Check if this request should be ignored
49
- if ((0, utils_1.shouldIgnorePath)(url, ignoreTraceRoutes))
50
- return originalMethod(config);
51
- const traceId = storage_1.storage.getStore()?.traceId;
52
- config = { ...config, headers: { ...config.headers, [traceHeaderKey]: traceId } };
53
- // Execute the request within a span
54
- return (0, span_1.startSpan)(`Outgoing HTTP request`, () => originalMethod(config), (options) => {
55
- const response = options
56
- ? options.error
57
- ? (0, axios_1.isAxiosError)(options.error)
58
- ? options.error.response
59
- : undefined
60
- : options.result
61
- : undefined;
62
- return { ...buildOutgoingHttpPayload(config, response), ...getPayload(config, response) };
63
- });
64
- };
42
+ }
43
+ ) => {
44
+ const createSpanWrappedRequest = (originalMethod, method) => {
45
+ const { headers: defaultHeaders, ...partialDefaultConfig } = client.defaults;
46
+ const headers = { ...defaultHeaders.common, ...(method && defaultHeaders[method]) };
47
+ const defaultConfig = { ...partialDefaultConfig, headers };
48
+ return async (config) => {
49
+ config = (0, axios_1.mergeConfig)(defaultConfig, config);
50
+ // Determine the actual config and URL
51
+ const url = [config.baseURL, config.url].filter(Boolean).join('');
52
+ // Check if this request should be ignored
53
+ if ((0, utils_1.shouldIgnorePath)(url, ignoreTraceRoutes)) return originalMethod(config);
54
+ const traceId = storage_1.storage.getStore()?.traceId;
55
+ config = { ...config, headers: { ...config.headers, [traceHeaderKey]: traceId } };
56
+ // Execute the request within a span
57
+ return (0, span_1.startSpan)(
58
+ `Outgoing HTTP request`,
59
+ () => originalMethod(config),
60
+ (options) => {
61
+ if (!options) return buildOutgoingHttpPayload(config);
62
+ if (options.error)
63
+ return buildOutgoingHttpPayload(
64
+ config,
65
+ (0, axios_1.isAxiosError)(options.error) ? options.error.response : undefined
66
+ );
67
+ return buildOutgoingHttpPayload(config, options.result);
68
+ }
69
+ );
65
70
  };
66
- const request = client.request.bind(client);
67
- const tracedRequest = createSpanWrappedRequest(request);
68
- client.request = tracedRequest;
69
- ['post', 'put', 'patch'].forEach((method) => {
70
- const func = createSpanWrappedRequest(request, method);
71
- client[method] = (url, data, config) => func({ ...config, method, url, data });
72
- });
73
- ['delete', 'get', 'head', 'options'].forEach((method) => {
74
- const func = createSpanWrappedRequest(request, method);
75
- client[method] = (url, config) => func({ ...config, method, url });
76
- });
77
- return client;
71
+ };
72
+ const request = client.request.bind(client);
73
+ const tracedRequest = createSpanWrappedRequest(request);
74
+ client.request = tracedRequest;
75
+ ['post', 'put', 'patch'].forEach((method) => {
76
+ const func = createSpanWrappedRequest(request, method);
77
+ client[method] = (url, data, config) => func({ ...config, method, url, data });
78
+ });
79
+ ['delete', 'get', 'head', 'options'].forEach((method) => {
80
+ const func = createSpanWrappedRequest(request, method);
81
+ client[method] = (url, config) => func({ ...config, method, url });
82
+ });
83
+ return client;
78
84
  };
79
85
  exports.traceAxios = traceAxios;