@autter/runtime-node 1.5.0 → 1.6.1

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.
@@ -90,6 +90,35 @@ var compat_manifest_default = {
90
90
  ingester: "1.5.0",
91
91
  migrations: ["0013-occurrence-codes"],
92
92
  sdks: { "@autter/runtime-node": "1.5.0", "@autter/runtime-next": "1.5.0", "@autter/runtime-browser": "1.4.0", "@autter/runtime-edge": "1.0.0" }
93
+ },
94
+ {
95
+ id: "breadcrumbs",
96
+ title: "Breadcrumbs: the steps before an error",
97
+ ingester: "1.6.0",
98
+ migrations: [],
99
+ sdks: { "@autter/runtime-browser": "1.6.0", "@autter/runtime-node": "1.6.0", "@autter/runtime-next": "1.6.0" }
100
+ },
101
+ {
102
+ id: "source_map_debug_ids",
103
+ title: "Source map debug ids",
104
+ ingester: "1.6.0",
105
+ migrations: ["0017-source-maps-debug-id"],
106
+ route: "/v1/sourcemaps/check",
107
+ sdks: { "@autter/runtime-browser": "1.6.0", "@autter/runtime-next": "1.6.0" }
108
+ },
109
+ {
110
+ id: "fingerprint_override",
111
+ title: "Fingerprint override",
112
+ ingester: "1.6.0",
113
+ migrations: [],
114
+ sdks: { "@autter/runtime-browser": "1.6.0", "@autter/runtime-node": "1.6.0", "@autter/runtime-next": "1.6.0", "@autter/runtime-edge": "1.1.0" }
115
+ },
116
+ {
117
+ id: "browser_trace_propagation",
118
+ title: "Browser trace propagation (browser errors linked to server traces)",
119
+ ingester: "1.6.0",
120
+ migrations: [],
121
+ sdks: { "@autter/runtime-browser": "1.6.0", "@autter/runtime-next": "1.6.0", "@autter/runtime-node": "1.6.0" }
93
122
  }
94
123
  ]
95
124
  };
@@ -435,7 +464,7 @@ import { request as httpsRequest } from "https";
435
464
  // package.json
436
465
  var package_default = {
437
466
  name: "@autter/runtime-node",
438
- version: "1.5.0",
467
+ version: "1.6.1",
439
468
  description: "Autter Runtime for Node.js: request wide events, coded errors, operation logging, same-origin browser relay and a curated OpenTelemetry server tracker",
440
469
  license: "MIT",
441
470
  type: "module",
@@ -486,6 +515,8 @@ var package_default = {
486
515
  "@autter/runtime-core": "0.0.0",
487
516
  "@types/node": "^22.10.0",
488
517
  express: "^4.21.2",
518
+ fastify: "^5.12.5",
519
+ koa: "^3.2.1",
489
520
  tsup: "^8.3.5",
490
521
  typescript: "^5.7.0"
491
522
  },
@@ -508,6 +539,55 @@ var package_default = {
508
539
  ]
509
540
  };
510
541
 
542
+ // src/shared.ts
543
+ var SHARED_STATE_KEY = /* @__PURE__ */ Symbol.for("@autter/runtime-node");
544
+ var SHARED_STATE_LAYOUT = 1;
545
+ function isObject(value) {
546
+ return typeof value === "object" && value !== null;
547
+ }
548
+ var VERSION = package_default.version;
549
+ function resolveShared() {
550
+ const fresh = { v: SHARED_STATE_LAYOUT, sdk: VERSION };
551
+ const host = globalThis;
552
+ let existing;
553
+ try {
554
+ existing = host[SHARED_STATE_KEY];
555
+ if (existing === void 0) {
556
+ Object.defineProperty(host, SHARED_STATE_KEY, {
557
+ value: fresh,
558
+ configurable: true,
559
+ enumerable: false,
560
+ writable: false
561
+ });
562
+ return fresh;
563
+ }
564
+ } catch {
565
+ return fresh;
566
+ }
567
+ if (isObject(existing) && existing.v === SHARED_STATE_LAYOUT) return existing;
568
+ debugLog(
569
+ `another copy of @autter/runtime-node uses shared state layout ${String(isObject(existing) ? existing.v : typeof existing)}; this copy (${VERSION}, layout ${SHARED_STATE_LAYOUT}) keeps its own state`
570
+ );
571
+ return fresh;
572
+ }
573
+ var shared = resolveShared();
574
+ function sharedSlot(name, init) {
575
+ const fresh = init();
576
+ try {
577
+ const existing = shared[name];
578
+ if (!isObject(existing)) {
579
+ shared[name] = fresh;
580
+ return fresh;
581
+ }
582
+ for (const [key, value] of Object.entries(fresh)) {
583
+ if (existing[key] === void 0) existing[key] = value;
584
+ }
585
+ return existing;
586
+ } catch {
587
+ return fresh;
588
+ }
589
+ }
590
+
511
591
  // src/compat.ts
512
592
  var SDK_IDENTITY = {
513
593
  name: "@autter/runtime-node",
@@ -600,7 +680,7 @@ function envDisabled() {
600
680
  return value === "0" || value === "false" || value === "off";
601
681
  }
602
682
  var defaultWarn = (message) => console.warn(`[autter-runtime] ${message}`);
603
- var state = freshState(null, false);
683
+ var compat = sharedSlot("compat", () => ({ state: freshState(null, false) }));
604
684
  function freshState(endpoint, enabled, sdk = SDK_IDENTITY, warn = defaultWarn) {
605
685
  return {
606
686
  endpoint,
@@ -615,7 +695,7 @@ function freshState(endpoint, enabled, sdk = SDK_IDENTITY, warn = defaultWarn) {
615
695
  };
616
696
  }
617
697
  function configureCompatCheck(options) {
618
- state = freshState(
698
+ compat.state = freshState(
619
699
  options.endpoint.replace(/\/$/, ""),
620
700
  options.enabled !== false && !envDisabled(),
621
701
  options.sdk ?? SDK_IDENTITY,
@@ -623,21 +703,21 @@ function configureCompatCheck(options) {
623
703
  );
624
704
  }
625
705
  function ensureCompatConfigured(endpoint) {
626
- if (state.endpoint === null && !envDisabled()) {
627
- state = freshState(endpoint.replace(/\/$/, ""), true);
706
+ if (compat.state.endpoint === null && !envDisabled()) {
707
+ compat.state = freshState(endpoint.replace(/\/$/, ""), true);
628
708
  }
629
709
  }
630
710
  function noteCompatFeature(id) {
631
711
  try {
632
- if (!state.enabled || state.features.has(id) || !featureById(id)) return;
633
- state.features.add(id);
634
- if (state.info) {
712
+ if (!compat.state.enabled || compat.state.features.has(id) || !featureById(id)) return;
713
+ compat.state.features.add(id);
714
+ if (compat.state.info) {
635
715
  evaluateAndWarn();
636
716
  return;
637
717
  }
638
- if (state.started) return;
639
- state.started = true;
640
- const current = state;
718
+ if (compat.state.started) return;
719
+ compat.state.started = true;
720
+ const current = compat.state;
641
721
  setTimeout(() => void runCheck(current), 0).unref();
642
722
  } catch {
643
723
  }
@@ -648,7 +728,7 @@ async function runCheck(current) {
648
728
  const { info, error } = await fetchIngesterCompat(current.endpoint, {
649
729
  probeRoutes: routesFor(current.features)
650
730
  });
651
- if (state !== current) return;
731
+ if (compat.state !== current) return;
652
732
  if (!info) {
653
733
  debugLog(`compat check skipped: ${error ?? "ingester version unknown"}`);
654
734
  return;
@@ -672,8 +752,8 @@ function routesFor(features) {
672
752
  return routes;
673
753
  }
674
754
  function mergeInfo(next) {
675
- const prev = state.info;
676
- state.info = {
755
+ const prev = compat.state.info;
756
+ compat.state.info = {
677
757
  version: next.version ?? prev?.version ?? null,
678
758
  ...next.legacy || prev?.legacy ? { legacy: true } : {},
679
759
  ...next.schema ?? prev?.schema ? { schema: next.schema ?? prev?.schema } : {},
@@ -681,17 +761,17 @@ function mergeInfo(next) {
681
761
  };
682
762
  }
683
763
  function evaluateAndWarn() {
684
- const info = state.info;
764
+ const info = compat.state.info;
685
765
  if (!info) return;
686
- if (info.version === null && state.endpoint) {
687
- const unprobed = routesFor(state.features).filter(
688
- (route) => info.routes?.[route] === void 0 && !state.pendingProbes.has(route)
766
+ if (info.version === null && compat.state.endpoint) {
767
+ const unprobed = routesFor(compat.state.features).filter(
768
+ (route) => info.routes?.[route] === void 0 && !compat.state.pendingProbes.has(route)
689
769
  );
690
770
  if (unprobed.length) {
691
- const current = state;
771
+ const current = compat.state;
692
772
  for (const route of unprobed) current.pendingProbes.add(route);
693
773
  void Promise.all(unprobed.map((route) => probeRoute(current.endpoint, route, {}).then((exists) => [route, exists]))).then((results) => {
694
- if (state !== current) return;
774
+ if (compat.state !== current) return;
695
775
  const routes = {};
696
776
  for (const [route, exists] of results) if (exists !== null) routes[route] = exists;
697
777
  mergeInfo({ version: null, legacy: true, routes });
@@ -700,31 +780,31 @@ function evaluateAndWarn() {
700
780
  });
701
781
  }
702
782
  }
703
- for (const issue of evaluateCompat({ features: state.features, ingester: info })) {
783
+ for (const issue of evaluateCompat({ features: compat.state.features, ingester: info })) {
704
784
  warnOnce(issue);
705
785
  }
706
786
  }
707
787
  function warnOnce(issue) {
708
788
  const key = `${issue.feature}:${issue.kind}`;
709
- if (state.warned.has(key)) return;
710
- state.warned.add(key);
789
+ if (compat.state.warned.has(key)) return;
790
+ compat.state.warned.add(key);
711
791
  try {
712
- state.warn(issue.message);
792
+ compat.state.warn(issue.message);
713
793
  } catch {
714
794
  }
715
795
  }
716
796
  function observeIngesterResponse(response) {
717
797
  try {
718
- if (!state.enabled) return;
798
+ if (!compat.state.enabled) return;
719
799
  const fromHeader = headerInfo(response.headers);
720
800
  if (fromHeader) {
721
- if (state.info?.version !== fromHeader.version) {
801
+ if (compat.state.info?.version !== fromHeader.version) {
722
802
  mergeInfo(fromHeader);
723
803
  evaluateAndWarn();
724
804
  }
725
805
  return;
726
806
  }
727
- if (response.status === 404 && response.route && !state.info?.version) {
807
+ if (response.status === 404 && response.route && !compat.state.info?.version) {
728
808
  mergeInfo({ version: null, legacy: true, routes: { [response.route]: false } });
729
809
  evaluateAndWarn();
730
810
  }
@@ -733,16 +813,16 @@ function observeIngesterResponse(response) {
733
813
  }
734
814
  function noteRelayRejection(eventTypes, status, headers) {
735
815
  try {
736
- if (!state.enabled || status !== 400 || headerInfo(headers)) return [];
816
+ if (!compat.state.enabled || status !== 400 || headerInfo(headers)) return [];
737
817
  const named = [];
738
818
  for (const id of featuresForBrowserEvents(eventTypes)) {
739
819
  const feature = featureById(id);
740
820
  const key = `${id}:relay_rejected`;
741
- if (state.warned.has(key)) continue;
742
- state.warned.add(key);
821
+ if (compat.state.warned.has(key)) continue;
822
+ compat.state.warned.add(key);
743
823
  named.push(id);
744
824
  try {
745
- state.warn(
825
+ compat.state.warn(
746
826
  `The ingester rejected a browser batch containing ${feature.title.toLowerCase()} events. ${feature.title} needs ingester >= ${feature.ingester}; yours is 1.4.0 or older (it predates version reporting), so those batches are dropped. ${ingesterUpgradeHint(COMPAT_MANIFEST)}`
747
827
  );
748
828
  } catch {
@@ -768,6 +848,7 @@ export {
768
848
  registerFlushTarget,
769
849
  unregisterFlushTargets,
770
850
  installAutterAutoFlush,
851
+ sharedSlot,
771
852
  SDK_IDENTITY,
772
853
  compatRequest,
773
854
  fetchIngesterCompat,
@@ -5,7 +5,7 @@ import {
5
5
  evaluateCompat,
6
6
  fetchIngesterCompat,
7
7
  versionAtLeast
8
- } from "./chunk-L7HWKMCZ.js";
8
+ } from "./chunk-HRDELHZP.js";
9
9
 
10
10
  // src/doctor.ts
11
11
  import { existsSync, readFileSync } from "fs";