@blyp/core 0.1.2 → 0.1.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.
Files changed (124) hide show
  1. package/README.md +56 -3
  2. package/dist/astro.js +4602 -0
  3. package/dist/astro.js.map +1 -0
  4. package/dist/astro.mjs +4574 -0
  5. package/dist/astro.mjs.map +1 -0
  6. package/dist/client.js +7 -0
  7. package/dist/client.js.map +1 -1
  8. package/dist/client.mjs +7 -0
  9. package/dist/client.mjs.map +1 -1
  10. package/dist/connectors/betterstack.js +24 -0
  11. package/dist/connectors/betterstack.js.map +1 -1
  12. package/dist/connectors/betterstack.mjs +24 -0
  13. package/dist/connectors/betterstack.mjs.map +1 -1
  14. package/dist/connectors/databuddy/index.d.ts +7 -0
  15. package/dist/connectors/databuddy/sender.d.ts +5 -0
  16. package/dist/connectors/databuddy.js +1456 -0
  17. package/dist/connectors/databuddy.js.map +1 -0
  18. package/dist/connectors/databuddy.mjs +1451 -0
  19. package/dist/connectors/databuddy.mjs.map +1 -0
  20. package/dist/connectors/otlp.js +24 -0
  21. package/dist/connectors/otlp.js.map +1 -1
  22. package/dist/connectors/otlp.mjs +24 -0
  23. package/dist/connectors/otlp.mjs.map +1 -1
  24. package/dist/connectors/posthog.js +24 -0
  25. package/dist/connectors/posthog.js.map +1 -1
  26. package/dist/connectors/posthog.mjs +24 -0
  27. package/dist/connectors/posthog.mjs.map +1 -1
  28. package/dist/connectors/sentry.js +24 -0
  29. package/dist/connectors/sentry.js.map +1 -1
  30. package/dist/connectors/sentry.mjs +24 -0
  31. package/dist/connectors/sentry.mjs.map +1 -1
  32. package/dist/core/config.d.ts +1 -1
  33. package/dist/core/logger.d.ts +3 -0
  34. package/dist/elysia.js +455 -30
  35. package/dist/elysia.js.map +1 -1
  36. package/dist/elysia.mjs +455 -30
  37. package/dist/elysia.mjs.map +1 -1
  38. package/dist/expo.js +7 -0
  39. package/dist/expo.js.map +1 -1
  40. package/dist/expo.mjs +7 -0
  41. package/dist/expo.mjs.map +1 -1
  42. package/dist/express.js +455 -30
  43. package/dist/express.js.map +1 -1
  44. package/dist/express.mjs +455 -30
  45. package/dist/express.mjs.map +1 -1
  46. package/dist/fastify.js +455 -30
  47. package/dist/fastify.js.map +1 -1
  48. package/dist/fastify.mjs +455 -30
  49. package/dist/fastify.mjs.map +1 -1
  50. package/dist/frameworks/astro/index.d.ts +2 -0
  51. package/dist/frameworks/astro/logger.d.ts +3 -0
  52. package/dist/frameworks/nitro/index.d.ts +2 -0
  53. package/dist/frameworks/nitro/logger.d.ts +6 -0
  54. package/dist/frameworks/nuxt/index.d.ts +2 -0
  55. package/dist/frameworks/nuxt/logger.d.ts +3 -0
  56. package/dist/frameworks/react-router/index.d.ts +2 -0
  57. package/dist/frameworks/react-router/logger.d.ts +3 -0
  58. package/dist/frameworks/shared/h3.d.ts +19 -0
  59. package/dist/hono.js +455 -30
  60. package/dist/hono.js.map +1 -1
  61. package/dist/hono.mjs +455 -30
  62. package/dist/hono.mjs.map +1 -1
  63. package/dist/index.d.ts +11 -1
  64. package/dist/index.js +1142 -78
  65. package/dist/index.js.map +1 -1
  66. package/dist/index.mjs +1135 -79
  67. package/dist/index.mjs.map +1 -1
  68. package/dist/nestjs.js +455 -30
  69. package/dist/nestjs.js.map +1 -1
  70. package/dist/nestjs.mjs +455 -30
  71. package/dist/nestjs.mjs.map +1 -1
  72. package/dist/nextjs.js +455 -30
  73. package/dist/nextjs.js.map +1 -1
  74. package/dist/nextjs.mjs +455 -30
  75. package/dist/nextjs.mjs.map +1 -1
  76. package/dist/nitro.js +4726 -0
  77. package/dist/nitro.js.map +1 -0
  78. package/dist/nitro.mjs +4698 -0
  79. package/dist/nitro.mjs.map +1 -0
  80. package/dist/nuxt.js +4733 -0
  81. package/dist/nuxt.js.map +1 -0
  82. package/dist/nuxt.mjs +4705 -0
  83. package/dist/nuxt.mjs.map +1 -0
  84. package/dist/react-router.js +4644 -0
  85. package/dist/react-router.js.map +1 -0
  86. package/dist/react-router.mjs +4616 -0
  87. package/dist/react-router.mjs.map +1 -0
  88. package/dist/standalone.js +423 -53
  89. package/dist/standalone.js.map +1 -1
  90. package/dist/standalone.mjs +423 -53
  91. package/dist/standalone.mjs.map +1 -1
  92. package/dist/sveltekit.js +455 -30
  93. package/dist/sveltekit.js.map +1 -1
  94. package/dist/sveltekit.mjs +455 -30
  95. package/dist/sveltekit.mjs.map +1 -1
  96. package/dist/tanstack-start.js +455 -30
  97. package/dist/tanstack-start.js.map +1 -1
  98. package/dist/tanstack-start.mjs +455 -30
  99. package/dist/tanstack-start.mjs.map +1 -1
  100. package/dist/types/connectors/databuddy.d.ts +52 -0
  101. package/dist/types/core/config.d.ts +32 -0
  102. package/dist/types/core/logger.d.ts +2 -0
  103. package/dist/types/frameworks/astro.d.ts +32 -0
  104. package/dist/types/frameworks/nitro.d.ts +62 -0
  105. package/dist/types/frameworks/nuxt.d.ts +12 -0
  106. package/dist/types/frameworks/react-router.d.ts +33 -0
  107. package/dist/types/frameworks/shared.d.ts +24 -0
  108. package/dist/types/shared/client-log.d.ts +1 -1
  109. package/exports/connectors/databuddy.js +1 -0
  110. package/exports/connectors/databuddy.mjs +1 -0
  111. package/exports/frameworks/astro.js +1 -0
  112. package/exports/frameworks/astro.mjs +1 -0
  113. package/exports/frameworks/nitro.js +1 -0
  114. package/exports/frameworks/nitro.mjs +1 -0
  115. package/exports/frameworks/nuxt.js +1 -0
  116. package/exports/frameworks/nuxt.mjs +1 -0
  117. package/exports/frameworks/react-router.js +1 -0
  118. package/exports/frameworks/react-router.mjs +1 -0
  119. package/package.json +59 -2
  120. package/types/connectors/databuddy.d.ts +1 -0
  121. package/types/frameworks/astro.d.ts +1 -0
  122. package/types/frameworks/nitro.d.ts +1 -0
  123. package/types/frameworks/nuxt.d.ts +1 -0
  124. package/types/frameworks/react-router.d.ts +1 -0
package/dist/fastify.mjs CHANGED
@@ -14,6 +14,7 @@ import { AsyncLocalStorage } from 'async_hooks';
14
14
  import { randomUUID } from 'crypto';
15
15
  import * as Sentry from '@sentry/node';
16
16
  import { Logtail } from '@logtail/node';
17
+ import { Databuddy } from '@databuddy/sdk/node';
17
18
 
18
19
  var __defProp = Object.defineProperty;
19
20
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -372,6 +373,7 @@ var CLIENT_LOG_LEVELS = [
372
373
  ];
373
374
  var clientConnectorRequestSchema = z.union([
374
375
  z.literal("betterstack"),
376
+ z.literal("databuddy"),
375
377
  z.literal("posthog"),
376
378
  z.literal("sentry"),
377
379
  z.undefined(),
@@ -412,16 +414,16 @@ function normalizeEndpointPath(path3) {
412
414
  }
413
415
 
414
416
  // src/shared/once.ts
415
- function createConsoleOnceLogger(method, warnedKeys6 = /* @__PURE__ */ new Set()) {
417
+ function createConsoleOnceLogger(method, warnedKeys7 = /* @__PURE__ */ new Set()) {
416
418
  return (key, message, error) => {
417
- if (warnedKeys6.has(key) || typeof console === "undefined") {
419
+ if (warnedKeys7.has(key) || typeof console === "undefined") {
418
420
  return;
419
421
  }
420
422
  const writer = console[method];
421
423
  if (typeof writer !== "function") {
422
424
  return;
423
425
  }
424
- warnedKeys6.add(key);
426
+ warnedKeys7.add(key);
425
427
  if (error === void 0) {
426
428
  writer.call(console, message);
427
429
  return;
@@ -429,11 +431,11 @@ function createConsoleOnceLogger(method, warnedKeys6 = /* @__PURE__ */ new Set()
429
431
  writer.call(console, message, error);
430
432
  };
431
433
  }
432
- function createWarnOnceLogger(warnedKeys6) {
433
- return createConsoleOnceLogger("warn", warnedKeys6);
434
+ function createWarnOnceLogger(warnedKeys7) {
435
+ return createConsoleOnceLogger("warn", warnedKeys7);
434
436
  }
435
- function createErrorOnceLogger(warnedKeys6) {
436
- return createConsoleOnceLogger("error", warnedKeys6);
437
+ function createErrorOnceLogger(warnedKeys7) {
438
+ return createConsoleOnceLogger("error", warnedKeys7);
437
439
  }
438
440
 
439
441
  // src/core/config.ts
@@ -799,6 +801,28 @@ function mergePostHogConnectorConfig(base, override) {
799
801
  }
800
802
  };
801
803
  }
804
+ function mergeDatabuddyConnectorConfig(base, override) {
805
+ const enabled = override?.enabled ?? base?.enabled ?? false;
806
+ const apiKey = override?.apiKey ?? base?.apiKey;
807
+ const websiteId = override?.websiteId ?? base?.websiteId;
808
+ const ready = enabled && hasNonEmptyString(apiKey) && hasNonEmptyString(websiteId);
809
+ return {
810
+ enabled,
811
+ mode: override?.mode ?? base?.mode ?? "auto",
812
+ apiKey,
813
+ websiteId,
814
+ namespace: override?.namespace ?? base?.namespace,
815
+ source: override?.source ?? base?.source,
816
+ apiUrl: override?.apiUrl ?? base?.apiUrl,
817
+ debug: override?.debug ?? base?.debug ?? false,
818
+ enableBatching: override?.enableBatching ?? base?.enableBatching ?? true,
819
+ batchSize: override?.batchSize ?? base?.batchSize,
820
+ batchTimeout: override?.batchTimeout ?? base?.batchTimeout,
821
+ maxQueueSize: override?.maxQueueSize ?? base?.maxQueueSize,
822
+ ready,
823
+ status: ready ? "enabled" : "missing"
824
+ };
825
+ }
802
826
  function mergeBetterStackConnectorConfig(base, override) {
803
827
  const sourceToken = override?.sourceToken ?? base?.sourceToken;
804
828
  const ingestingHost = override?.ingestingHost ?? base?.ingestingHost;
@@ -889,6 +913,7 @@ function mergeOTLPConnectorsConfig(base, override) {
889
913
  function mergeConnectorsConfig(base, override) {
890
914
  return {
891
915
  betterstack: mergeBetterStackConnectorConfig(base?.betterstack, override?.betterstack),
916
+ databuddy: mergeDatabuddyConnectorConfig(base?.databuddy, override?.databuddy),
892
917
  posthog: mergePostHogConnectorConfig(base?.posthog, override?.posthog),
893
918
  sentry: mergeSentryConnectorConfig(base?.sentry, override?.sentry),
894
919
  otlp: mergeOTLPConnectorsConfig(base?.otlp, override?.otlp)
@@ -2527,12 +2552,320 @@ function createBetterStackSender(config) {
2527
2552
  };
2528
2553
  }
2529
2554
  var warnedKeys4 = /* @__PURE__ */ new Set();
2555
+ var senderCache = /* @__PURE__ */ new Map();
2530
2556
  var testHooks3 = {};
2531
2557
  var warnOnce5 = createErrorOnceLogger(warnedKeys4);
2532
- function getSentryModule2() {
2533
- return testHooks3.module ?? Sentry;
2558
+ function registerShutdownHooks3(key, shutdown) {
2559
+ const handlers = ["beforeExit", "SIGINT", "SIGTERM"];
2560
+ for (const event of handlers) {
2561
+ process.once(event, () => {
2562
+ void shutdown().catch((error) => {
2563
+ warnOnce5(
2564
+ `${key}:shutdown`,
2565
+ "[Blyp] Failed to flush Databuddy telemetry during shutdown.",
2566
+ error
2567
+ );
2568
+ });
2569
+ });
2570
+ }
2534
2571
  }
2535
2572
  function resolveConnectorConfig3(config) {
2573
+ const connector = isBlypConfig(config) ? config.connectors?.databuddy : config;
2574
+ const enabled = connector?.enabled ?? false;
2575
+ const apiKey = connector?.apiKey;
2576
+ const websiteId = connector?.websiteId;
2577
+ const ready = enabled && hasNonEmptyString(apiKey) && hasNonEmptyString(websiteId);
2578
+ return {
2579
+ enabled,
2580
+ mode: connector?.mode ?? "auto",
2581
+ apiKey,
2582
+ websiteId,
2583
+ namespace: connector?.namespace,
2584
+ source: connector?.source,
2585
+ apiUrl: connector?.apiUrl,
2586
+ debug: connector?.debug ?? false,
2587
+ enableBatching: connector?.enableBatching ?? true,
2588
+ batchSize: connector?.batchSize,
2589
+ batchTimeout: connector?.batchTimeout,
2590
+ maxQueueSize: connector?.maxQueueSize,
2591
+ ready,
2592
+ status: ready ? "enabled" : "missing"
2593
+ };
2594
+ }
2595
+ function createDefaultClient2(connector) {
2596
+ return new Databuddy({
2597
+ apiKey: connector.apiKey ?? "",
2598
+ ...connector.websiteId ? { websiteId: connector.websiteId } : {},
2599
+ ...connector.namespace ? { namespace: connector.namespace } : {},
2600
+ ...connector.source ? { source: connector.source } : {},
2601
+ ...connector.apiUrl ? { apiUrl: connector.apiUrl } : {},
2602
+ debug: connector.debug,
2603
+ enableBatching: connector.enableBatching,
2604
+ ...connector.batchSize !== void 0 ? { batchSize: connector.batchSize } : {},
2605
+ ...connector.batchTimeout !== void 0 ? { batchTimeout: connector.batchTimeout } : {},
2606
+ ...connector.maxQueueSize !== void 0 ? { maxQueueSize: connector.maxQueueSize } : {}
2607
+ });
2608
+ }
2609
+ function getDatabuddySenderKey(connector) {
2610
+ return JSON.stringify({
2611
+ enabled: connector.enabled,
2612
+ mode: connector.mode,
2613
+ apiKey: connector.apiKey ?? null,
2614
+ websiteId: connector.websiteId ?? null,
2615
+ namespace: connector.namespace ?? null,
2616
+ source: connector.source ?? null,
2617
+ apiUrl: connector.apiUrl ?? null,
2618
+ debug: connector.debug,
2619
+ enableBatching: connector.enableBatching,
2620
+ batchSize: connector.batchSize ?? null,
2621
+ batchTimeout: connector.batchTimeout ?? null,
2622
+ maxQueueSize: connector.maxQueueSize ?? null
2623
+ });
2624
+ }
2625
+ function getSessionId(record) {
2626
+ const direct = getField(record, "sessionId");
2627
+ if (hasNonEmptyString(direct)) {
2628
+ return direct;
2629
+ }
2630
+ return getClientSessionField(record, "sessionId");
2631
+ }
2632
+ function getAnonymousId(record) {
2633
+ const direct = getField(record, "anonymousId");
2634
+ if (hasNonEmptyString(direct)) {
2635
+ return direct;
2636
+ }
2637
+ const payload = getPrimaryPayload(record);
2638
+ if (isPlainObject(payload.metadata) && hasNonEmptyString(payload.metadata.databuddyAnonymousId)) {
2639
+ return payload.metadata.databuddyAnonymousId;
2640
+ }
2641
+ return void 0;
2642
+ }
2643
+ function getDatabuddyEventName(record) {
2644
+ const recordType = getRecordType(record);
2645
+ if (hasNonEmptyString(recordType)) {
2646
+ return recordType;
2647
+ }
2648
+ return "log";
2649
+ }
2650
+ function buildRecordProperties(record, source) {
2651
+ const properties = {
2652
+ blyp_level: record.level,
2653
+ blyp_source: source,
2654
+ blyp_payload: serializeLogRecord(record),
2655
+ message: typeof record.message === "string" ? record.message : String(record.message)
2656
+ };
2657
+ const caller = typeof record.caller === "string" ? record.caller : void 0;
2658
+ const groupId = getField(record, "groupId");
2659
+ const method = getField(record, "method");
2660
+ const path3 = getField(record, "path");
2661
+ const status = getField(record, "status");
2662
+ const duration = getField(record, "duration");
2663
+ const pagePath = getClientPageField(record, "pathname");
2664
+ const pageUrl = getClientPageField(record, "url");
2665
+ const sessionId = getClientSessionField(record, "sessionId");
2666
+ const pageId = getClientSessionField(record, "pageId");
2667
+ const ifTruthy = [
2668
+ ["blyp_type", getRecordType(record)],
2669
+ ["caller", caller],
2670
+ ["group_id", groupId],
2671
+ ["method", method],
2672
+ ["path", path3],
2673
+ ["page_path", pagePath],
2674
+ ["page_url", pageUrl],
2675
+ ["session_id", sessionId],
2676
+ ["page_id", pageId]
2677
+ ];
2678
+ const ifDefined = [
2679
+ ["status_code", status],
2680
+ ["duration_ms", duration]
2681
+ ];
2682
+ for (const [key, value] of ifTruthy) {
2683
+ if (value) {
2684
+ properties[key] = value;
2685
+ }
2686
+ }
2687
+ for (const [key, value] of ifDefined) {
2688
+ if (value !== void 0) {
2689
+ properties[key] = value;
2690
+ }
2691
+ }
2692
+ return properties;
2693
+ }
2694
+ function createTrackEvent(record, source) {
2695
+ return {
2696
+ name: getDatabuddyEventName(record),
2697
+ anonymousId: getAnonymousId(record),
2698
+ sessionId: getSessionId(record),
2699
+ properties: buildRecordProperties(record, source)
2700
+ };
2701
+ }
2702
+ function normalizeExceptionProperties2(value) {
2703
+ if (!isPlainObject(value)) {
2704
+ return {};
2705
+ }
2706
+ return normalizeLogValue(value);
2707
+ }
2708
+ function normalizeExceptionInput3(value, fallbackMessage) {
2709
+ if (value instanceof Error) {
2710
+ return {
2711
+ message: value.message || fallbackMessage,
2712
+ properties: {
2713
+ error_type: value.name,
2714
+ ...value.stack ? { stack: value.stack } : {},
2715
+ ...normalizeExceptionProperties2(value)
2716
+ }
2717
+ };
2718
+ }
2719
+ if (isPlainObject(value)) {
2720
+ const message = hasNonEmptyString(value.message) ? value.message : hasNonEmptyString(value.error) ? value.error : fallbackMessage;
2721
+ return {
2722
+ message,
2723
+ properties: normalizeExceptionProperties2(value)
2724
+ };
2725
+ }
2726
+ if (typeof value === "string") {
2727
+ return {
2728
+ message: value,
2729
+ properties: {
2730
+ message: value
2731
+ }
2732
+ };
2733
+ }
2734
+ return {
2735
+ message: fallbackMessage,
2736
+ properties: {
2737
+ value: normalizeLogValue(value)
2738
+ }
2739
+ };
2740
+ }
2741
+ function createDatabuddySender(config) {
2742
+ const connector = resolveConnectorConfig3(config);
2743
+ const senderKey = getDatabuddySenderKey(connector);
2744
+ const cached = senderCache.get(senderKey);
2745
+ if (cached) {
2746
+ return cached;
2747
+ }
2748
+ const key = `${connector.apiUrl ?? "default"}:${connector.mode}:${connector.apiKey ?? "missing"}`;
2749
+ const client = connector.ready ? testHooks3.createClient?.(connector) ?? createDefaultClient2(connector) : void 0;
2750
+ if (client) {
2751
+ registerShutdownHooks3(key, async () => {
2752
+ await client.flush();
2753
+ });
2754
+ }
2755
+ const emitUnavailableWarning = () => {
2756
+ warnOnce5(
2757
+ `databuddy-unavailable:${key}`,
2758
+ "[Blyp] Databuddy connector is not configured. Databuddy requires both apiKey and websiteId. Skipping Databuddy delivery."
2759
+ );
2760
+ };
2761
+ const emitExceptionUnavailableWarning = () => {
2762
+ warnOnce5(
2763
+ `databuddy-exception-unavailable:${key}`,
2764
+ "[Blyp] Databuddy error tracking is not configured. Databuddy requires both apiKey and websiteId. Skipping Databuddy exception capture."
2765
+ );
2766
+ };
2767
+ const sender = {
2768
+ enabled: connector.enabled,
2769
+ ready: connector.ready,
2770
+ mode: connector.mode,
2771
+ status: connector.status,
2772
+ shouldAutoForwardServerLogs() {
2773
+ return connector.ready && connector.mode === "auto";
2774
+ },
2775
+ shouldAutoCaptureExceptions() {
2776
+ return connector.ready && connector.mode === "auto";
2777
+ },
2778
+ send(record, options = {}) {
2779
+ if (!connector.ready || !client) {
2780
+ if (options.warnIfUnavailable) {
2781
+ emitUnavailableWarning();
2782
+ }
2783
+ return;
2784
+ }
2785
+ try {
2786
+ const result = client.track(createTrackEvent(record, options.source ?? "server"));
2787
+ if (result && typeof result.catch === "function") {
2788
+ void result.catch((error) => {
2789
+ warnOnce5(
2790
+ `databuddy-send:${key}`,
2791
+ "[Blyp] Failed to deliver log to Databuddy.",
2792
+ error
2793
+ );
2794
+ });
2795
+ }
2796
+ } catch (error) {
2797
+ warnOnce5(
2798
+ `databuddy-send:${key}`,
2799
+ "[Blyp] Failed to deliver log to Databuddy.",
2800
+ error
2801
+ );
2802
+ }
2803
+ },
2804
+ captureException(error, options = {}) {
2805
+ if (!connector.ready || !client) {
2806
+ if (options.warnIfUnavailable) {
2807
+ emitExceptionUnavailableWarning();
2808
+ }
2809
+ return;
2810
+ }
2811
+ const normalized = normalizeExceptionInput3(
2812
+ error,
2813
+ options.source === "client" ? "Client error" : "Server error"
2814
+ );
2815
+ try {
2816
+ const result = client.track({
2817
+ name: "error",
2818
+ anonymousId: options.anonymousId,
2819
+ sessionId: options.sessionId,
2820
+ properties: {
2821
+ message: normalized.message,
2822
+ blyp_source: options.source ?? "server",
2823
+ blyp_level: "error",
2824
+ ...normalized.properties,
2825
+ ...options.properties ?? {}
2826
+ }
2827
+ });
2828
+ if (result && typeof result.catch === "function") {
2829
+ void result.catch((captureError) => {
2830
+ warnOnce5(
2831
+ `databuddy-capture:${key}`,
2832
+ "[Blyp] Failed to capture exception in Databuddy.",
2833
+ captureError
2834
+ );
2835
+ });
2836
+ }
2837
+ } catch (captureError) {
2838
+ warnOnce5(
2839
+ `databuddy-capture:${key}`,
2840
+ "[Blyp] Failed to capture exception in Databuddy.",
2841
+ captureError
2842
+ );
2843
+ }
2844
+ },
2845
+ async flush() {
2846
+ try {
2847
+ if (client) {
2848
+ await client.flush();
2849
+ }
2850
+ } catch (error) {
2851
+ warnOnce5(
2852
+ `databuddy-flush:${key}`,
2853
+ "[Blyp] Failed to flush Databuddy telemetry.",
2854
+ error
2855
+ );
2856
+ }
2857
+ }
2858
+ };
2859
+ senderCache.set(senderKey, sender);
2860
+ return sender;
2861
+ }
2862
+ var warnedKeys5 = /* @__PURE__ */ new Set();
2863
+ var testHooks4 = {};
2864
+ var warnOnce6 = createErrorOnceLogger(warnedKeys5);
2865
+ function getSentryModule2() {
2866
+ return testHooks4.module ?? Sentry;
2867
+ }
2868
+ function resolveConnectorConfig4(config) {
2536
2869
  const connector = isBlypConfig(config) ? config.connectors?.sentry : config;
2537
2870
  const enabled = connector?.enabled ?? false;
2538
2871
  const dsn = connector?.dsn;
@@ -2677,7 +3010,7 @@ function hasConfigMismatch(connector, client) {
2677
3010
  return hasNonEmptyString(connector.dsn) && connector.dsn !== options.dsn || hasNonEmptyString(connector.environment) && connector.environment !== options.environment || hasNonEmptyString(connector.release) && connector.release !== options.release;
2678
3011
  }
2679
3012
  function createSentrySender(config) {
2680
- const connector = resolveConnectorConfig3(config);
3013
+ const connector = resolveConnectorConfig4(config);
2681
3014
  const key = `${connector.mode}:${connector.dsn ?? "missing"}`;
2682
3015
  const module = getSentryModule2();
2683
3016
  let client = connector.enabled ? module.getClient() : void 0;
@@ -2691,7 +3024,7 @@ function createSentrySender(config) {
2691
3024
  });
2692
3025
  client = module.getClient();
2693
3026
  } catch (error) {
2694
- warnOnce5(
3027
+ warnOnce6(
2695
3028
  `sentry-init:${key}`,
2696
3029
  "[Blyp] Failed to initialize Sentry. Skipping Sentry delivery.",
2697
3030
  error
@@ -2699,14 +3032,14 @@ function createSentrySender(config) {
2699
3032
  }
2700
3033
  }
2701
3034
  if (client && hasConfigMismatch(connector, client)) {
2702
- warnOnce5(
3035
+ warnOnce6(
2703
3036
  `sentry-mismatch:${key}`,
2704
3037
  "[Blyp] Sentry is already initialized with different options. Reusing the existing Sentry client."
2705
3038
  );
2706
3039
  }
2707
3040
  const ready = connector.enabled && client !== void 0;
2708
3041
  const emitUnavailableWarning = () => {
2709
- warnOnce5(
3042
+ warnOnce6(
2710
3043
  `sentry-unavailable:${key}`,
2711
3044
  "[Blyp] Sentry connector is not configured. Skipping Sentry delivery."
2712
3045
  );
@@ -2732,7 +3065,7 @@ function createSentrySender(config) {
2732
3065
  try {
2733
3066
  logMethod(record.message, attributes);
2734
3067
  } catch (error) {
2735
- warnOnce5(
3068
+ warnOnce6(
2736
3069
  `sentry-log:${key}`,
2737
3070
  "[Blyp] Failed to deliver log to Sentry.",
2738
3071
  error
@@ -2750,7 +3083,7 @@ function createSentrySender(config) {
2750
3083
  module.captureException(exception);
2751
3084
  });
2752
3085
  } catch (error) {
2753
- warnOnce5(
3086
+ warnOnce6(
2754
3087
  `sentry-exception:${key}`,
2755
3088
  "[Blyp] Failed to capture exception in Sentry.",
2756
3089
  error
@@ -2761,7 +3094,7 @@ function createSentrySender(config) {
2761
3094
  try {
2762
3095
  await module.flush(2e3);
2763
3096
  } catch (error) {
2764
- warnOnce5(
3097
+ warnOnce6(
2765
3098
  `sentry-flush:${key}`,
2766
3099
  "[Blyp] Failed to flush Sentry logs.",
2767
3100
  error
@@ -2770,9 +3103,9 @@ function createSentrySender(config) {
2770
3103
  }
2771
3104
  };
2772
3105
  }
2773
- var warnedKeys5 = /* @__PURE__ */ new Set();
2774
- var testHooks4 = {};
2775
- var warnOnce6 = createErrorOnceLogger(warnedKeys5);
3106
+ var warnedKeys6 = /* @__PURE__ */ new Set();
3107
+ var testHooks5 = {};
3108
+ var warnOnce7 = createErrorOnceLogger(warnedKeys6);
2776
3109
  function normalizeOTLPRecord(record, connector, source = "server") {
2777
3110
  const severity = resolveSeverity2(record.level);
2778
3111
  const body = typeof record.message === "string" ? record.message : String(record.message);
@@ -2837,14 +3170,14 @@ function resolveSeverity2(level) {
2837
3170
  return { text: "info", number: SeverityNumber.INFO };
2838
3171
  }
2839
3172
  }
2840
- function registerShutdownHooks3(key, shutdown) {
3173
+ function registerShutdownHooks4(key, shutdown) {
2841
3174
  const handlers = ["beforeExit", "SIGINT", "SIGTERM"];
2842
3175
  for (const event of handlers) {
2843
3176
  process.once(event, async () => {
2844
3177
  try {
2845
3178
  await shutdown();
2846
3179
  } catch (error) {
2847
- warnOnce6(
3180
+ warnOnce7(
2848
3181
  `${key}:shutdown`,
2849
3182
  "[Blyp] Failed to flush OTLP logs during shutdown.",
2850
3183
  error
@@ -2921,7 +3254,7 @@ function createUnavailableSender(name, connector) {
2921
3254
  const senderName = name || connector?.name || "otlp";
2922
3255
  const key = `${senderName}:${connector?.serviceName ?? "blyp-app"}:${connector?.endpoint ?? "missing"}`;
2923
3256
  const emitUnavailableWarning = () => {
2924
- warnOnce6(
3257
+ warnOnce7(
2925
3258
  `otlp-unavailable:${key}`,
2926
3259
  `[Blyp] OTLP target "${senderName}" is not configured or not ready. Skipping OTLP delivery.`
2927
3260
  );
@@ -2952,7 +3285,7 @@ function createSender(connector) {
2952
3285
  ...connector,
2953
3286
  headers: resolveTransportHeaders(connector)
2954
3287
  };
2955
- const transport = testHooks4.createTransport?.(transportConnector) ?? createDefaultTransport2(transportConnector);
3288
+ const transport = testHooks5.createTransport?.(transportConnector) ?? createDefaultTransport2(transportConnector);
2956
3289
  return {
2957
3290
  name: connector.name,
2958
3291
  enabled: connector.enabled,
@@ -2968,7 +3301,7 @@ function createSender(connector) {
2968
3301
  const result = transport.emit(normalized);
2969
3302
  if (result && typeof result.catch === "function") {
2970
3303
  void result.catch((error) => {
2971
- warnOnce6(
3304
+ warnOnce7(
2972
3305
  `otlp-emit:${key}`,
2973
3306
  `[Blyp] Failed to deliver log to OTLP target "${connector.name}".`,
2974
3307
  error
@@ -2976,7 +3309,7 @@ function createSender(connector) {
2976
3309
  });
2977
3310
  }
2978
3311
  } catch (error) {
2979
- warnOnce6(
3312
+ warnOnce7(
2980
3313
  `otlp-emit:${key}`,
2981
3314
  `[Blyp] Failed to deliver log to OTLP target "${connector.name}".`,
2982
3315
  error
@@ -2989,7 +3322,7 @@ function createSender(connector) {
2989
3322
  await transport.flush();
2990
3323
  }
2991
3324
  } catch (error) {
2992
- warnOnce6(
3325
+ warnOnce7(
2993
3326
  `otlp-flush:${key}`,
2994
3327
  `[Blyp] Failed to flush OTLP logs for target "${connector.name}".`,
2995
3328
  error
@@ -3018,7 +3351,7 @@ function createOTLPRegistry(config) {
3018
3351
  await Promise.all(Array.from(senders.values()).map((sender) => sender.flush()));
3019
3352
  }
3020
3353
  };
3021
- registerShutdownHooks3("otlp-registry", () => registry.flush());
3354
+ registerShutdownHooks4("otlp-registry", () => registry.flush());
3022
3355
  return registry;
3023
3356
  }
3024
3357
  var _RuntimeDetector = class _RuntimeDetector {
@@ -3409,6 +3742,9 @@ function getPostHogSender(logger2) {
3409
3742
  function getBetterStackSender(logger2) {
3410
3743
  return getLoggerFactory(logger2).betterstack;
3411
3744
  }
3745
+ function getDatabuddySender(logger2) {
3746
+ return getLoggerFactory(logger2).databuddy;
3747
+ }
3412
3748
  function tryGetPostHogSender(logger2) {
3413
3749
  try {
3414
3750
  return getPostHogSender(logger2);
@@ -3423,6 +3759,13 @@ function tryGetBetterStackSender(logger2) {
3423
3759
  return null;
3424
3760
  }
3425
3761
  }
3762
+ function tryGetDatabuddySender(logger2) {
3763
+ try {
3764
+ return getDatabuddySender(logger2);
3765
+ } catch {
3766
+ return null;
3767
+ }
3768
+ }
3426
3769
  function getSentrySender(logger2) {
3427
3770
  return getLoggerFactory(logger2).sentry;
3428
3771
  }
@@ -3482,6 +3825,18 @@ function maybeSendToBetterStack(betterstack, record) {
3482
3825
  }
3483
3826
  betterstack.send(record, { source: "server", warnIfUnavailable: true });
3484
3827
  }
3828
+ function maybeSendToDatabuddy(databuddy, record) {
3829
+ if (isClientLogRecord(record)) {
3830
+ return;
3831
+ }
3832
+ if (!databuddy.shouldAutoForwardServerLogs()) {
3833
+ if (databuddy.enabled && !databuddy.ready) {
3834
+ databuddy.send(record, { source: "server", warnIfUnavailable: true });
3835
+ }
3836
+ return;
3837
+ }
3838
+ databuddy.send(record, { source: "server", warnIfUnavailable: true });
3839
+ }
3485
3840
  function maybeSendToSentry(sentry, record) {
3486
3841
  if (isClientLogRecord(record)) {
3487
3842
  return;
@@ -3502,7 +3857,7 @@ function maybeSendToOTLP(otlp, record) {
3502
3857
  sender.send(record, { source: "server", warnIfUnavailable: true });
3503
3858
  }
3504
3859
  }
3505
- function createLoggerInstance(rootRawLogger, sink, betterstack, posthog, sentry, otlp, bindings = {}, source = "root") {
3860
+ function createLoggerInstance(rootRawLogger, sink, betterstack, databuddy, posthog, sentry, otlp, bindings = {}, source = "root") {
3506
3861
  const rawLogger = Object.keys(bindings).length > 0 ? rootRawLogger.child(bindings) : rootRawLogger;
3507
3862
  const writeRecord = (level, message, args, writeSource = source) => {
3508
3863
  if (writeSource === "root" && shouldDropRootLogWrite()) {
@@ -3528,6 +3883,7 @@ function createLoggerInstance(rootRawLogger, sink, betterstack, posthog, sentry,
3528
3883
  );
3529
3884
  sink.write(record);
3530
3885
  maybeSendToBetterStack(betterstack, record);
3886
+ maybeSendToDatabuddy(databuddy, record);
3531
3887
  maybeSendToPostHog(posthog, record);
3532
3888
  maybeSendToSentry(sentry, record);
3533
3889
  maybeSendToOTLP(otlp, record);
@@ -3551,6 +3907,7 @@ function createLoggerInstance(rootRawLogger, sink, betterstack, posthog, sentry,
3551
3907
  sink.write(record);
3552
3908
  }
3553
3909
  maybeSendToBetterStack(betterstack, record);
3910
+ maybeSendToDatabuddy(databuddy, record);
3554
3911
  maybeSendToPostHog(posthog, record);
3555
3912
  maybeSendToSentry(sentry, record);
3556
3913
  maybeSendToOTLP(otlp, record);
@@ -3584,8 +3941,26 @@ function createLoggerInstance(rootRawLogger, sink, betterstack, posthog, sentry,
3584
3941
  }
3585
3942
  writeRecord("table", message, data === void 0 ? [] : [data]);
3586
3943
  },
3587
- flush: () => sink.flush(),
3588
- shutdown: () => sink.shutdown(),
3944
+ flush: async () => {
3945
+ await sink.flush();
3946
+ await Promise.allSettled([
3947
+ betterstack.flush(),
3948
+ databuddy.flush(),
3949
+ posthog.flush(),
3950
+ sentry.flush(),
3951
+ otlp.flush()
3952
+ ]);
3953
+ },
3954
+ shutdown: async () => {
3955
+ await sink.shutdown();
3956
+ await Promise.allSettled([
3957
+ betterstack.flush(),
3958
+ databuddy.flush(),
3959
+ posthog.flush(),
3960
+ sentry.flush(),
3961
+ otlp.flush()
3962
+ ]);
3963
+ },
3589
3964
  createStructuredLog: (groupId, initial) => {
3590
3965
  return createStructuredLogForLogger(logger2, groupId, {
3591
3966
  initialFields: initial
@@ -3597,6 +3972,7 @@ function createLoggerInstance(rootRawLogger, sink, betterstack, posthog, sentry,
3597
3972
  rootRawLogger,
3598
3973
  sink,
3599
3974
  betterstack,
3975
+ databuddy,
3600
3976
  posthog,
3601
3977
  sentry,
3602
3978
  otlp,
@@ -3607,6 +3983,7 @@ function createLoggerInstance(rootRawLogger, sink, betterstack, posthog, sentry,
3607
3983
  [LOGGER_FACTORY]: {
3608
3984
  bindings,
3609
3985
  betterstack,
3986
+ databuddy,
3610
3987
  posthog,
3611
3988
  sentry,
3612
3989
  otlp,
@@ -3616,6 +3993,7 @@ function createLoggerInstance(rootRawLogger, sink, betterstack, posthog, sentry,
3616
3993
  rootRawLogger,
3617
3994
  sink,
3618
3995
  betterstack,
3996
+ databuddy,
3619
3997
  posthog,
3620
3998
  sentry,
3621
3999
  otlp,
@@ -3639,6 +4017,7 @@ function createBaseLogger(config) {
3639
4017
  const rawLogger = createPinoLogger(resolvedConfig);
3640
4018
  const sink = createPrimarySink(resolvedConfig);
3641
4019
  const betterstack = createBetterStackSender(resolvedConfig);
4020
+ const databuddy = createDatabuddySender(resolvedConfig);
3642
4021
  const posthog = createPostHogSender(resolvedConfig);
3643
4022
  const sentry = createSentrySender(resolvedConfig);
3644
4023
  const otlp = createOTLPRegistry(resolvedConfig);
@@ -3646,6 +4025,7 @@ function createBaseLogger(config) {
3646
4025
  rawLogger,
3647
4026
  sink,
3648
4027
  betterstack,
4028
+ databuddy,
3649
4029
  posthog,
3650
4030
  sentry,
3651
4031
  otlp
@@ -3728,6 +4108,7 @@ function resolveServerLogger(config = {}, loggerOverride) {
3728
4108
  return {
3729
4109
  logger: logger2,
3730
4110
  betterstack: getBetterStackSender(logger2),
4111
+ databuddy: getDatabuddySender(logger2),
3731
4112
  posthog: getPostHogSender(logger2),
3732
4113
  sentry: getSentrySender(logger2),
3733
4114
  otlp: getOtlpRegistry(logger2),
@@ -3847,6 +4228,22 @@ function emitHttpErrorLog(logger2, level, request, path3, statusCode, responseTi
3847
4228
  }
3848
4229
  });
3849
4230
  }
4231
+ const databuddy = tryGetDatabuddySender(logger2);
4232
+ if (databuddy?.shouldAutoCaptureExceptions()) {
4233
+ databuddy.captureException(captureContext.error ?? error ?? message, {
4234
+ source: "server",
4235
+ warnIfUnavailable: true,
4236
+ properties: {
4237
+ method: request.method,
4238
+ path: path3,
4239
+ status_code: statusCode,
4240
+ ...request.url ? { current_url: request.url } : {},
4241
+ ...getHeaderValue(request.headers, "user-agent") ? { user_agent: getHeaderValue(request.headers, "user-agent") } : {},
4242
+ ...errorLogData.ip ? { ip: errorLogData.ip } : {},
4243
+ payload: errorLogData
4244
+ }
4245
+ });
4246
+ }
3850
4247
  return errorLogData;
3851
4248
  }
3852
4249
  async function parseClientLogPayload(request, body) {
@@ -3938,6 +4335,34 @@ async function handleClientLogIngestion(options) {
3938
4335
  });
3939
4336
  }
3940
4337
  }
4338
+ } else if (payload.connector === "databuddy") {
4339
+ headers["x-blyp-databuddy-status"] = config.databuddy.ready ? "enabled" : "missing";
4340
+ if (config.databuddy.ready) {
4341
+ const forwardedRecord = {
4342
+ timestamp: structuredPayload.receivedAt,
4343
+ level: payload.level,
4344
+ message: `[client] ${payload.message}`,
4345
+ data: structuredPayload
4346
+ };
4347
+ config.databuddy.send(forwardedRecord, {
4348
+ source: "client"
4349
+ });
4350
+ if ((payload.level === "error" || payload.level === "critical") && config.databuddy.shouldAutoCaptureExceptions()) {
4351
+ const clientErrorCandidate = payload.data && typeof payload.data === "object" && !Array.isArray(payload.data) && typeof payload.data.message === "string" ? payload.data : payload.message;
4352
+ config.databuddy.captureException(clientErrorCandidate, {
4353
+ source: "client",
4354
+ warnIfUnavailable: true,
4355
+ sessionId: payload.session.sessionId,
4356
+ properties: {
4357
+ page_url: payload.page.url,
4358
+ page_path: payload.page.pathname,
4359
+ client_runtime: payload.device?.runtime,
4360
+ metadata: payload.metadata,
4361
+ payload: structuredPayload
4362
+ }
4363
+ });
4364
+ }
4365
+ }
3941
4366
  } else if (payload.connector === "posthog") {
3942
4367
  headers["x-blyp-posthog-status"] = config.posthog.ready ? "enabled" : "missing";
3943
4368
  if (config.posthog.ready) {