@interfere/react 0.1.0-alpha.2 → 0.1.0-alpha.25

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 (205) hide show
  1. package/dist/error-boundary.d.mts +27 -0
  2. package/dist/error-boundary.d.mts.map +1 -0
  3. package/dist/error-boundary.mjs +42 -0
  4. package/dist/error-boundary.mjs.map +1 -0
  5. package/dist/internal/client.d.mts +13 -0
  6. package/dist/internal/client.d.mts.map +1 -0
  7. package/dist/internal/client.mjs +80 -0
  8. package/dist/internal/client.mjs.map +1 -0
  9. package/dist/internal/config.d.mts +9 -0
  10. package/dist/internal/config.d.mts.map +1 -0
  11. package/dist/internal/config.mjs +27 -0
  12. package/dist/internal/config.mjs.map +1 -0
  13. package/dist/internal/context.d.mts +6 -0
  14. package/dist/internal/context.d.mts.map +1 -0
  15. package/dist/internal/context.mjs +32 -0
  16. package/dist/internal/context.mjs.map +1 -0
  17. package/dist/internal/envelope.d.mts +14 -0
  18. package/dist/internal/envelope.d.mts.map +1 -0
  19. package/dist/internal/envelope.mjs +20 -0
  20. package/dist/internal/envelope.mjs.map +1 -0
  21. package/dist/internal/errors.d.mts +4 -0
  22. package/dist/internal/errors.d.mts.map +1 -0
  23. package/dist/internal/errors.mjs +4 -0
  24. package/dist/internal/errors.mjs.map +1 -0
  25. package/dist/internal/sw.d.mts +4 -0
  26. package/dist/internal/sw.d.mts.map +1 -0
  27. package/dist/internal/sw.mjs +10 -0
  28. package/dist/internal/sw.mjs.map +1 -0
  29. package/dist/plugins/errors.d.mts +6 -0
  30. package/dist/plugins/errors.d.mts.map +1 -0
  31. package/dist/plugins/errors.mjs +59 -0
  32. package/dist/plugins/errors.mjs.map +1 -0
  33. package/dist/plugins/lib/loader.d.mts +9 -0
  34. package/dist/plugins/lib/loader.d.mts.map +1 -0
  35. package/dist/plugins/lib/loader.mjs +47 -0
  36. package/dist/plugins/lib/loader.mjs.map +1 -0
  37. package/dist/plugins/lib/types.d.mts +14 -0
  38. package/dist/plugins/lib/types.d.mts.map +1 -0
  39. package/dist/plugins/lib/types.mjs +1 -0
  40. package/dist/plugins/pages.d.mts +6 -0
  41. package/dist/plugins/pages.d.mts.map +1 -0
  42. package/dist/plugins/pages.mjs +102 -0
  43. package/dist/plugins/pages.mjs.map +1 -0
  44. package/dist/plugins/rage-clicks.d.mts +6 -0
  45. package/dist/plugins/rage-clicks.d.mts.map +1 -0
  46. package/dist/plugins/rage-clicks.mjs +53 -0
  47. package/dist/plugins/rage-clicks.mjs.map +1 -0
  48. package/dist/plugins/replay.d.mts +6 -0
  49. package/dist/plugins/replay.d.mts.map +1 -0
  50. package/dist/plugins/replay.mjs +62 -0
  51. package/dist/plugins/replay.mjs.map +1 -0
  52. package/dist/provider.d.mts +17 -11
  53. package/dist/provider.d.mts.map +1 -1
  54. package/dist/provider.mjs +18 -17
  55. package/dist/provider.mjs.map +1 -1
  56. package/dist/tracking/api.d.mts +22 -0
  57. package/dist/tracking/api.d.mts.map +1 -0
  58. package/dist/tracking/api.mjs +88 -0
  59. package/dist/tracking/api.mjs.map +1 -0
  60. package/dist/tracking/session.d.mts +19 -0
  61. package/dist/tracking/session.d.mts.map +1 -0
  62. package/dist/tracking/session.mjs +92 -0
  63. package/dist/tracking/session.mjs.map +1 -0
  64. package/dist/tracking/visitor.d.mts +6 -0
  65. package/dist/tracking/visitor.d.mts.map +1 -0
  66. package/dist/tracking/visitor.mjs +35 -0
  67. package/dist/tracking/visitor.mjs.map +1 -0
  68. package/dist/transport/http.d.mts +15 -0
  69. package/dist/transport/http.d.mts.map +1 -0
  70. package/dist/transport/http.mjs +56 -0
  71. package/dist/transport/http.mjs.map +1 -0
  72. package/dist/transport/queue.d.mts +25 -0
  73. package/dist/transport/queue.d.mts.map +1 -0
  74. package/dist/transport/queue.mjs +60 -0
  75. package/dist/transport/queue.mjs.map +1 -0
  76. package/dist/util/log.d.mts +13 -0
  77. package/dist/util/log.d.mts.map +1 -0
  78. package/dist/util/log.mjs +37 -0
  79. package/dist/util/log.mjs.map +1 -0
  80. package/package.json +47 -70
  81. package/dist/client.d.mts +0 -15
  82. package/dist/client.d.mts.map +0 -1
  83. package/dist/client.mjs +0 -75
  84. package/dist/client.mjs.map +0 -1
  85. package/dist/core/events/event-registry.d.mts +0 -23
  86. package/dist/core/events/event-registry.d.mts.map +0 -1
  87. package/dist/core/events/event-registry.mjs +0 -32
  88. package/dist/core/events/event-registry.mjs.map +0 -1
  89. package/dist/core/events/plugin-event-types.d.mts +0 -92
  90. package/dist/core/events/plugin-event-types.d.mts.map +0 -1
  91. package/dist/core/events/plugin-event-types.mjs +0 -25
  92. package/dist/core/events/plugin-event-types.mjs.map +0 -1
  93. package/dist/core/plugins/dom-utils.d.mts +0 -9
  94. package/dist/core/plugins/dom-utils.d.mts.map +0 -1
  95. package/dist/core/plugins/dom-utils.mjs +0 -25
  96. package/dist/core/plugins/dom-utils.mjs.map +0 -1
  97. package/dist/core/plugins/impl/ai-summary.d.mts +0 -6
  98. package/dist/core/plugins/impl/ai-summary.d.mts.map +0 -1
  99. package/dist/core/plugins/impl/ai-summary.mjs +0 -122
  100. package/dist/core/plugins/impl/ai-summary.mjs.map +0 -1
  101. package/dist/core/plugins/impl/errors.d.mts +0 -9
  102. package/dist/core/plugins/impl/errors.d.mts.map +0 -1
  103. package/dist/core/plugins/impl/errors.mjs +0 -153
  104. package/dist/core/plugins/impl/errors.mjs.map +0 -1
  105. package/dist/core/plugins/impl/page-events.d.mts +0 -15
  106. package/dist/core/plugins/impl/page-events.d.mts.map +0 -1
  107. package/dist/core/plugins/impl/page-events.mjs +0 -131
  108. package/dist/core/plugins/impl/page-events.mjs.map +0 -1
  109. package/dist/core/plugins/impl/rage-click.d.mts +0 -6
  110. package/dist/core/plugins/impl/rage-click.d.mts.map +0 -1
  111. package/dist/core/plugins/impl/rage-click.mjs +0 -53
  112. package/dist/core/plugins/impl/rage-click.mjs.map +0 -1
  113. package/dist/core/plugins/impl/replay.d.mts +0 -9
  114. package/dist/core/plugins/impl/replay.d.mts.map +0 -1
  115. package/dist/core/plugins/impl/replay.mjs +0 -144
  116. package/dist/core/plugins/impl/replay.mjs.map +0 -1
  117. package/dist/core/plugins/impl/server-tracing.d.mts +0 -7
  118. package/dist/core/plugins/impl/server-tracing.d.mts.map +0 -1
  119. package/dist/core/plugins/impl/server-tracing.mjs +0 -160
  120. package/dist/core/plugins/impl/server-tracing.mjs.map +0 -1
  121. package/dist/core/plugins/plugin-event-system.d.mts +0 -47
  122. package/dist/core/plugins/plugin-event-system.d.mts.map +0 -1
  123. package/dist/core/plugins/plugin-event-system.mjs +0 -75
  124. package/dist/core/plugins/plugin-event-system.mjs.map +0 -1
  125. package/dist/core/plugins/plugin-loader.d.mts +0 -22
  126. package/dist/core/plugins/plugin-loader.d.mts.map +0 -1
  127. package/dist/core/plugins/plugin-loader.mjs +0 -142
  128. package/dist/core/plugins/plugin-loader.mjs.map +0 -1
  129. package/dist/core/runtime/config.d.mts +0 -14
  130. package/dist/core/runtime/config.d.mts.map +0 -1
  131. package/dist/core/runtime/config.mjs +0 -39
  132. package/dist/core/runtime/config.mjs.map +0 -1
  133. package/dist/core/runtime/context.d.mts +0 -25
  134. package/dist/core/runtime/context.d.mts.map +0 -1
  135. package/dist/core/runtime/context.mjs +0 -48
  136. package/dist/core/runtime/context.mjs.map +0 -1
  137. package/dist/core/runtime/ingest-target.d.mts +0 -10
  138. package/dist/core/runtime/ingest-target.d.mts.map +0 -1
  139. package/dist/core/runtime/ingest-target.mjs +0 -15
  140. package/dist/core/runtime/ingest-target.mjs.map +0 -1
  141. package/dist/core/schemas.d.mts +0 -85
  142. package/dist/core/schemas.d.mts.map +0 -1
  143. package/dist/core/schemas.mjs +0 -1
  144. package/dist/effect/build-envelope.d.mts +0 -9
  145. package/dist/effect/build-envelope.d.mts.map +0 -1
  146. package/dist/effect/build-envelope.mjs +0 -29
  147. package/dist/effect/build-envelope.mjs.map +0 -1
  148. package/dist/effect/errors.d.mts +0 -36
  149. package/dist/effect/errors.d.mts.map +0 -1
  150. package/dist/effect/errors.mjs +0 -10
  151. package/dist/effect/errors.mjs.map +0 -1
  152. package/dist/effect/layers/config.layer.d.mts +0 -13
  153. package/dist/effect/layers/config.layer.d.mts.map +0 -1
  154. package/dist/effect/layers/config.layer.mjs +0 -21
  155. package/dist/effect/layers/config.layer.mjs.map +0 -1
  156. package/dist/effect/layers/context.layer.d.mts +0 -12
  157. package/dist/effect/layers/context.layer.d.mts.map +0 -1
  158. package/dist/effect/layers/context.layer.mjs +0 -14
  159. package/dist/effect/layers/context.layer.mjs.map +0 -1
  160. package/dist/effect/layers/http.layer.d.mts +0 -21
  161. package/dist/effect/layers/http.layer.d.mts.map +0 -1
  162. package/dist/effect/layers/http.layer.mjs +0 -113
  163. package/dist/effect/layers/http.layer.mjs.map +0 -1
  164. package/dist/effect/layers/queue.layer.d.mts +0 -30
  165. package/dist/effect/layers/queue.layer.d.mts.map +0 -1
  166. package/dist/effect/layers/queue.layer.mjs +0 -232
  167. package/dist/effect/layers/queue.layer.mjs.map +0 -1
  168. package/dist/effect/layers/session.layer.d.mts +0 -26
  169. package/dist/effect/layers/session.layer.d.mts.map +0 -1
  170. package/dist/effect/layers/session.layer.mjs +0 -126
  171. package/dist/effect/layers/session.layer.mjs.map +0 -1
  172. package/dist/effect/layers/storage.layer.d.mts +0 -19
  173. package/dist/effect/layers/storage.layer.d.mts.map +0 -1
  174. package/dist/effect/layers/storage.layer.mjs +0 -200
  175. package/dist/effect/layers/storage.layer.mjs.map +0 -1
  176. package/dist/effect/layers/tracer.layer.d.mts +0 -9
  177. package/dist/effect/layers/tracer.layer.d.mts.map +0 -1
  178. package/dist/effect/layers/tracer.layer.mjs +0 -11
  179. package/dist/effect/layers/tracer.layer.mjs.map +0 -1
  180. package/dist/effect/runtime-services.d.mts +0 -22
  181. package/dist/effect/runtime-services.d.mts.map +0 -1
  182. package/dist/effect/runtime-services.mjs +0 -76
  183. package/dist/effect/runtime-services.mjs.map +0 -1
  184. package/dist/effect/tags.d.mts +0 -50
  185. package/dist/effect/tags.d.mts.map +0 -1
  186. package/dist/effect/tags.mjs +0 -7
  187. package/dist/effect/tags.mjs.map +0 -1
  188. package/dist/hooks/use-runtime-and-plugins.d.mts +0 -7
  189. package/dist/hooks/use-runtime-and-plugins.d.mts.map +0 -1
  190. package/dist/hooks/use-runtime-and-plugins.mjs +0 -153
  191. package/dist/hooks/use-runtime-and-plugins.mjs.map +0 -1
  192. package/dist/hooks/use-session.d.mts +0 -40
  193. package/dist/hooks/use-session.d.mts.map +0 -1
  194. package/dist/hooks/use-session.mjs +0 -96
  195. package/dist/hooks/use-session.mjs.map +0 -1
  196. package/dist/package.mjs +0 -100
  197. package/dist/package.mjs.map +0 -1
  198. package/dist/server/auth.d.mts +0 -11
  199. package/dist/server/auth.d.mts.map +0 -1
  200. package/dist/server/auth.mjs +0 -36
  201. package/dist/server/auth.mjs.map +0 -1
  202. package/dist/server/capture.d.mts +0 -18
  203. package/dist/server/capture.d.mts.map +0 -1
  204. package/dist/server/capture.mjs +0 -105
  205. package/dist/server/capture.mjs.map +0 -1
@@ -0,0 +1,35 @@
1
+ import { createLogger } from "../util/log.mjs";
2
+ //#region src/tracking/visitor.ts
3
+ const log = createLogger("visitor");
4
+ let visitorId = null;
5
+ let pending = null;
6
+ function resolveApiKey() {
7
+ if (typeof process === "undefined") return;
8
+ return process.env.INTERFERE_FINGERPRINT_KEY ?? void 0;
9
+ }
10
+ function initVisitor() {
11
+ const apiKey = resolveApiKey();
12
+ if (!apiKey) {
13
+ log.info("no INTERFERE_FINGERPRINT_KEY, skipping");
14
+ return;
15
+ }
16
+ pending = (async () => {
17
+ try {
18
+ visitorId = (await (await (await import("@fingerprintjs/fingerprintjs-pro")).load({ apiKey })).get()).visitorId;
19
+ log.debug("resolved %s", visitorId);
20
+ return visitorId;
21
+ } catch {
22
+ log.error("fingerprint failed");
23
+ return null;
24
+ }
25
+ })();
26
+ }
27
+ function getVisitorId() {
28
+ return visitorId;
29
+ }
30
+ function whenVisitorReady() {
31
+ if (visitorId) return Promise.resolve(visitorId);
32
+ return pending ?? Promise.resolve(null);
33
+ }
34
+ //#endregion
35
+ export { getVisitorId, initVisitor, whenVisitorReady };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visitor.mjs","names":[],"sources":["../../src/tracking/visitor.ts"],"sourcesContent":["import { createLogger } from \"../util/log.js\";\n\nconst log = createLogger(\"visitor\");\n\nlet visitorId: string | null = null;\nlet pending: Promise<string | null> | null = null;\n\nfunction resolveApiKey(): string | undefined {\n if (typeof process === \"undefined\") {\n return undefined;\n }\n return process.env.INTERFERE_FINGERPRINT_KEY ?? undefined;\n}\n\nexport function initVisitor(): void {\n const apiKey = resolveApiKey();\n if (!apiKey) {\n log.info(\"no INTERFERE_FINGERPRINT_KEY, skipping\");\n return;\n }\n\n pending = (async () => {\n try {\n const FingerprintJS = await import(\"@fingerprintjs/fingerprintjs-pro\");\n\n const fp = await FingerprintJS.load({ apiKey });\n const result = await fp.get();\n\n visitorId = result.visitorId;\n\n log.debug(\"resolved %s\", visitorId);\n\n return visitorId;\n } catch {\n log.error(\"fingerprint failed\");\n\n return null;\n }\n })();\n}\n\nexport function getVisitorId(): string | null {\n return visitorId;\n}\n\nexport function whenVisitorReady(): Promise<string | null> {\n if (visitorId) {\n return Promise.resolve(visitorId);\n }\n return pending ?? Promise.resolve(null);\n}\n"],"mappings":";;AAEA,MAAM,MAAM,aAAa,UAAU;AAEnC,IAAI,YAA2B;AAC/B,IAAI,UAAyC;AAE7C,SAAS,gBAAoC;AAC3C,KAAI,OAAO,YAAY,YACrB;AAEF,QAAO,QAAQ,IAAI,6BAA6B,KAAA;;AAGlD,SAAgB,cAAoB;CAClC,MAAM,SAAS,eAAe;AAC9B,KAAI,CAAC,QAAQ;AACX,MAAI,KAAK,yCAAyC;AAClD;;AAGF,YAAW,YAAY;AACrB,MAAI;AAMF,gBAFe,OADJ,OAFW,MAAM,OAAO,qCAEJ,KAAK,EAAE,QAAQ,CAAC,EACvB,KAAK,EAEV;AAEnB,OAAI,MAAM,eAAe,UAAU;AAEnC,UAAO;UACD;AACN,OAAI,MAAM,qBAAqB;AAE/B,UAAO;;KAEP;;AAGN,SAAgB,eAA8B;AAC5C,QAAO;;AAGT,SAAgB,mBAA2C;AACzD,KAAI,UACF,QAAO,QAAQ,QAAQ,UAAU;AAEnC,QAAO,WAAW,QAAQ,QAAQ,KAAK"}
@@ -0,0 +1,15 @@
1
+ import { Envelope } from "@interfere/types/sdk/envelope";
2
+
3
+ //#region src/transport/http.d.ts
4
+ interface IngestTarget {
5
+ headers: Headers;
6
+ url: string;
7
+ }
8
+ declare class HttpTransport {
9
+ private readonly target;
10
+ private pendingKeepalive;
11
+ constructor(target: IngestTarget);
12
+ send(envelopes: Envelope[]): Promise<void>;
13
+ }
14
+ //#endregion
15
+ export { HttpTransport, IngestTarget };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.mts","names":[],"sources":["../../src/transport/http.ts"],"mappings":";;;UAUiB,YAAA;EACf,OAAA,EAAS,OAAA;EACT,GAAA;AAAA;AAAA,cA+BW,aAAA;EAAA,iBACM,MAAA;EAAA,QACT,gBAAA;cAEI,MAAA,EAAQ,YAAA;EAId,IAAA,CAAK,SAAA,EAAW,QAAA,KAAa,OAAA;AAAA"}
@@ -0,0 +1,56 @@
1
+ import { createLogger } from "../util/log.mjs";
2
+ import { getVisitorId } from "../tracking/visitor.mjs";
3
+ import { session } from "../tracking/api.mjs";
4
+ import { make } from "tctx/traceparent";
5
+ //#region src/transport/http.ts
6
+ const log = createLogger("http");
7
+ function buildHeaders(base) {
8
+ const h = Object.fromEntries(base.entries());
9
+ h.traceparent = String(make());
10
+ const sessionId = session.getId();
11
+ if (sessionId) h["x-interfere-session"] = sessionId;
12
+ const visitorId = getVisitorId();
13
+ if (visitorId) h["x-interfere-visitor"] = visitorId;
14
+ return h;
15
+ }
16
+ function hasServiceWorker() {
17
+ return typeof navigator !== "undefined" && "serviceWorker" in navigator && navigator.serviceWorker.controller !== null;
18
+ }
19
+ const KEEPALIVE_BUDGET_BYTES = 61440;
20
+ const MAX_CONCURRENT_KEEPALIVE = 15;
21
+ var HttpTransport = class {
22
+ target;
23
+ pendingKeepalive = 0;
24
+ constructor(target) {
25
+ this.target = target;
26
+ }
27
+ async send(envelopes) {
28
+ const body = JSON.stringify(envelopes);
29
+ const headers = buildHeaders(this.target.headers);
30
+ if (hasServiceWorker()) {
31
+ log.debug("POST %d envelopes via SW", envelopes.length);
32
+ await fetch(this.target.url, {
33
+ method: "POST",
34
+ headers,
35
+ body
36
+ });
37
+ return;
38
+ }
39
+ const bytes = new TextEncoder().encode(body).byteLength;
40
+ const useKeepalive = bytes < KEEPALIVE_BUDGET_BYTES && this.pendingKeepalive < MAX_CONCURRENT_KEEPALIVE;
41
+ if (useKeepalive) this.pendingKeepalive++;
42
+ log.debug("POST %d envelopes direct (%d bytes, keepalive=%s)", envelopes.length, bytes, useKeepalive);
43
+ try {
44
+ await fetch(this.target.url, {
45
+ method: "POST",
46
+ headers,
47
+ body,
48
+ keepalive: useKeepalive
49
+ });
50
+ } finally {
51
+ if (useKeepalive) this.pendingKeepalive--;
52
+ }
53
+ }
54
+ };
55
+ //#endregion
56
+ export { HttpTransport };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.mjs","names":[],"sources":["../../src/transport/http.ts"],"sourcesContent":["import type { Envelope } from \"@interfere/types/sdk/envelope\";\n\nimport { make } from \"tctx/traceparent\";\n\nimport { session } from \"../tracking/api.js\";\nimport { getVisitorId } from \"../tracking/visitor.js\";\nimport { createLogger } from \"../util/log.js\";\n\nconst log = createLogger(\"http\");\n\nexport interface IngestTarget {\n headers: Headers;\n url: string;\n}\n\nfunction buildHeaders(base: Headers): Record<string, string> {\n const h: Record<string, string> = Object.fromEntries(base.entries());\n h.traceparent = String(make());\n\n const sessionId = session.getId();\n if (sessionId) {\n h[\"x-interfere-session\"] = sessionId;\n }\n\n const visitorId = getVisitorId();\n if (visitorId) {\n h[\"x-interfere-visitor\"] = visitorId;\n }\n\n return h;\n}\n\nfunction hasServiceWorker(): boolean {\n return (\n typeof navigator !== \"undefined\" &&\n \"serviceWorker\" in navigator &&\n navigator.serviceWorker.controller !== null\n );\n}\n\nconst KEEPALIVE_BUDGET_BYTES = 61_440;\nconst MAX_CONCURRENT_KEEPALIVE = 15;\n\nexport class HttpTransport {\n private readonly target: IngestTarget;\n private pendingKeepalive = 0;\n\n constructor(target: IngestTarget) {\n this.target = target;\n }\n\n async send(envelopes: Envelope[]): Promise<void> {\n const body = JSON.stringify(envelopes);\n const headers = buildHeaders(this.target.headers);\n\n if (hasServiceWorker()) {\n log.debug(\"POST %d envelopes via SW\", envelopes.length);\n await fetch(this.target.url, {\n method: \"POST\",\n headers,\n body,\n });\n return;\n }\n\n const bytes = new TextEncoder().encode(body).byteLength;\n const useKeepalive =\n bytes < KEEPALIVE_BUDGET_BYTES &&\n this.pendingKeepalive < MAX_CONCURRENT_KEEPALIVE;\n\n if (useKeepalive) {\n this.pendingKeepalive++;\n }\n\n log.debug(\n \"POST %d envelopes direct (%d bytes, keepalive=%s)\",\n envelopes.length,\n bytes,\n useKeepalive\n );\n\n try {\n await fetch(this.target.url, {\n method: \"POST\",\n headers,\n body,\n keepalive: useKeepalive,\n });\n } finally {\n if (useKeepalive) {\n this.pendingKeepalive--;\n }\n }\n }\n}\n"],"mappings":";;;;;AAQA,MAAM,MAAM,aAAa,OAAO;AAOhC,SAAS,aAAa,MAAuC;CAC3D,MAAM,IAA4B,OAAO,YAAY,KAAK,SAAS,CAAC;AACpE,GAAE,cAAc,OAAO,MAAM,CAAC;CAE9B,MAAM,YAAY,QAAQ,OAAO;AACjC,KAAI,UACF,GAAE,yBAAyB;CAG7B,MAAM,YAAY,cAAc;AAChC,KAAI,UACF,GAAE,yBAAyB;AAG7B,QAAO;;AAGT,SAAS,mBAA4B;AACnC,QACE,OAAO,cAAc,eACrB,mBAAmB,aACnB,UAAU,cAAc,eAAe;;AAI3C,MAAM,yBAAyB;AAC/B,MAAM,2BAA2B;AAEjC,IAAa,gBAAb,MAA2B;CACzB;CACA,mBAA2B;CAE3B,YAAY,QAAsB;AAChC,OAAK,SAAS;;CAGhB,MAAM,KAAK,WAAsC;EAC/C,MAAM,OAAO,KAAK,UAAU,UAAU;EACtC,MAAM,UAAU,aAAa,KAAK,OAAO,QAAQ;AAEjD,MAAI,kBAAkB,EAAE;AACtB,OAAI,MAAM,4BAA4B,UAAU,OAAO;AACvD,SAAM,MAAM,KAAK,OAAO,KAAK;IAC3B,QAAQ;IACR;IACA;IACD,CAAC;AACF;;EAGF,MAAM,QAAQ,IAAI,aAAa,CAAC,OAAO,KAAK,CAAC;EAC7C,MAAM,eACJ,QAAQ,0BACR,KAAK,mBAAmB;AAE1B,MAAI,aACF,MAAK;AAGP,MAAI,MACF,qDACA,UAAU,QACV,OACA,aACD;AAED,MAAI;AACF,SAAM,MAAM,KAAK,OAAO,KAAK;IAC3B,QAAQ;IACR;IACA;IACA,WAAW;IACZ,CAAC;YACM;AACR,OAAI,aACF,MAAK"}
@@ -0,0 +1,25 @@
1
+ import { HttpTransport } from "./http.mjs";
2
+ import { Envelope } from "@interfere/types/sdk/envelope";
3
+
4
+ //#region src/transport/queue.d.ts
5
+ interface QueueOptions {
6
+ batchMs?: number;
7
+ batchSize?: number;
8
+ transport: HttpTransport;
9
+ }
10
+ declare class BatchQueue {
11
+ private readonly buffer;
12
+ private timer;
13
+ private readonly batchSize;
14
+ private readonly batchMs;
15
+ private readonly transport;
16
+ constructor(opts: QueueOptions);
17
+ start(): void;
18
+ enqueue(envelope: Envelope): void;
19
+ flush(): void;
20
+ dispose(): void;
21
+ private readonly onVisibilityChange;
22
+ private readonly onBeforeUnload;
23
+ }
24
+ //#endregion
25
+ export { BatchQueue, QueueOptions };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.mts","names":[],"sources":["../../src/transport/queue.ts"],"mappings":";;;;UAUiB,YAAA;EACf,OAAA;EACA,SAAA;EACA,SAAA,EAAW,aAAA;AAAA;AAAA,cAGA,UAAA;EAAA,iBACM,MAAA;EAAA,QACT,KAAA;EAAA,iBACS,SAAA;EAAA,iBACA,OAAA;EAAA,iBACA,SAAA;cAEL,IAAA,EAAM,YAAA;EAMlB,KAAA,CAAA;EAeA,OAAA,CAAQ,QAAA,EAAU,QAAA;EAOlB,KAAA,CAAA;EAWA,OAAA,CAAA;EAAA,iBAiBiB,kBAAA;EAAA,iBAMA,cAAA;AAAA"}
@@ -0,0 +1,60 @@
1
+ import { createLogger } from "../util/log.mjs";
2
+ //#region src/transport/queue.ts
3
+ const log = createLogger("queue");
4
+ const DEFAULT_BATCH_SIZE = 10;
5
+ const DEFAULT_BATCH_MS = 250;
6
+ var BatchQueue = class {
7
+ buffer = [];
8
+ timer = null;
9
+ batchSize;
10
+ batchMs;
11
+ transport;
12
+ constructor(opts) {
13
+ this.batchSize = opts.batchSize ?? DEFAULT_BATCH_SIZE;
14
+ this.batchMs = opts.batchMs ?? DEFAULT_BATCH_MS;
15
+ this.transport = opts.transport;
16
+ }
17
+ start() {
18
+ if (this.timer) return;
19
+ this.timer = setInterval(() => {
20
+ this.flush();
21
+ }, this.batchMs);
22
+ if (typeof globalThis.addEventListener === "function") {
23
+ globalThis.addEventListener("visibilitychange", this.onVisibilityChange);
24
+ globalThis.addEventListener("beforeunload", this.onBeforeUnload);
25
+ }
26
+ }
27
+ enqueue(envelope) {
28
+ this.buffer.push(envelope);
29
+ if (this.buffer.length >= this.batchSize) this.flush();
30
+ }
31
+ flush() {
32
+ while (this.buffer.length > 0) {
33
+ const batch = this.buffer.splice(0, this.batchSize);
34
+ log.debug("flushing %d envelopes", batch.length);
35
+ this.transport.send(batch).catch(() => {
36
+ log.warn("send failed, re-queuing %d envelopes", batch.length);
37
+ this.buffer.unshift(...batch);
38
+ });
39
+ }
40
+ }
41
+ dispose() {
42
+ if (this.timer) {
43
+ clearInterval(this.timer);
44
+ this.timer = null;
45
+ }
46
+ if (typeof globalThis.removeEventListener === "function") {
47
+ globalThis.removeEventListener("visibilitychange", this.onVisibilityChange);
48
+ globalThis.removeEventListener("beforeunload", this.onBeforeUnload);
49
+ }
50
+ this.flush();
51
+ }
52
+ onVisibilityChange = () => {
53
+ if (document.visibilityState === "hidden") this.flush();
54
+ };
55
+ onBeforeUnload = () => {
56
+ this.flush();
57
+ };
58
+ };
59
+ //#endregion
60
+ export { BatchQueue };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.mjs","names":[],"sources":["../../src/transport/queue.ts"],"sourcesContent":["import type { Envelope } from \"@interfere/types/sdk/envelope\";\n\nimport { createLogger } from \"../util/log.js\";\nimport type { HttpTransport } from \"./http.js\";\n\nconst log = createLogger(\"queue\");\n\nconst DEFAULT_BATCH_SIZE = 10;\nconst DEFAULT_BATCH_MS = 250;\n\nexport interface QueueOptions {\n batchMs?: number;\n batchSize?: number;\n transport: HttpTransport;\n}\n\nexport class BatchQueue {\n private readonly buffer: Envelope[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private readonly batchSize: number;\n private readonly batchMs: number;\n private readonly transport: HttpTransport;\n\n constructor(opts: QueueOptions) {\n this.batchSize = opts.batchSize ?? DEFAULT_BATCH_SIZE;\n this.batchMs = opts.batchMs ?? DEFAULT_BATCH_MS;\n this.transport = opts.transport;\n }\n\n start(): void {\n if (this.timer) {\n return;\n }\n\n this.timer = setInterval(() => {\n this.flush();\n }, this.batchMs);\n\n if (typeof globalThis.addEventListener === \"function\") {\n globalThis.addEventListener(\"visibilitychange\", this.onVisibilityChange);\n globalThis.addEventListener(\"beforeunload\", this.onBeforeUnload);\n }\n }\n\n enqueue(envelope: Envelope): void {\n this.buffer.push(envelope);\n if (this.buffer.length >= this.batchSize) {\n this.flush();\n }\n }\n\n flush(): void {\n while (this.buffer.length > 0) {\n const batch = this.buffer.splice(0, this.batchSize);\n log.debug(\"flushing %d envelopes\", batch.length);\n this.transport.send(batch).catch(() => {\n log.warn(\"send failed, re-queuing %d envelopes\", batch.length);\n this.buffer.unshift(...batch);\n });\n }\n }\n\n dispose(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n\n if (typeof globalThis.removeEventListener === \"function\") {\n globalThis.removeEventListener(\n \"visibilitychange\",\n this.onVisibilityChange\n );\n globalThis.removeEventListener(\"beforeunload\", this.onBeforeUnload);\n }\n\n this.flush();\n }\n\n private readonly onVisibilityChange = (): void => {\n if (document.visibilityState === \"hidden\") {\n this.flush();\n }\n };\n\n private readonly onBeforeUnload = (): void => {\n this.flush();\n };\n}\n"],"mappings":";;AAKA,MAAM,MAAM,aAAa,QAAQ;AAEjC,MAAM,qBAAqB;AAC3B,MAAM,mBAAmB;AAQzB,IAAa,aAAb,MAAwB;CACtB,SAAsC,EAAE;CACxC,QAAuD;CACvD;CACA;CACA;CAEA,YAAY,MAAoB;AAC9B,OAAK,YAAY,KAAK,aAAa;AACnC,OAAK,UAAU,KAAK,WAAW;AAC/B,OAAK,YAAY,KAAK;;CAGxB,QAAc;AACZ,MAAI,KAAK,MACP;AAGF,OAAK,QAAQ,kBAAkB;AAC7B,QAAK,OAAO;KACX,KAAK,QAAQ;AAEhB,MAAI,OAAO,WAAW,qBAAqB,YAAY;AACrD,cAAW,iBAAiB,oBAAoB,KAAK,mBAAmB;AACxE,cAAW,iBAAiB,gBAAgB,KAAK,eAAe;;;CAIpE,QAAQ,UAA0B;AAChC,OAAK,OAAO,KAAK,SAAS;AAC1B,MAAI,KAAK,OAAO,UAAU,KAAK,UAC7B,MAAK,OAAO;;CAIhB,QAAc;AACZ,SAAO,KAAK,OAAO,SAAS,GAAG;GAC7B,MAAM,QAAQ,KAAK,OAAO,OAAO,GAAG,KAAK,UAAU;AACnD,OAAI,MAAM,yBAAyB,MAAM,OAAO;AAChD,QAAK,UAAU,KAAK,MAAM,CAAC,YAAY;AACrC,QAAI,KAAK,wCAAwC,MAAM,OAAO;AAC9D,SAAK,OAAO,QAAQ,GAAG,MAAM;KAC7B;;;CAIN,UAAgB;AACd,MAAI,KAAK,OAAO;AACd,iBAAc,KAAK,MAAM;AACzB,QAAK,QAAQ;;AAGf,MAAI,OAAO,WAAW,wBAAwB,YAAY;AACxD,cAAW,oBACT,oBACA,KAAK,mBACN;AACD,cAAW,oBAAoB,gBAAgB,KAAK,eAAe;;AAGrE,OAAK,OAAO;;CAGd,2BAAkD;AAChD,MAAI,SAAS,oBAAoB,SAC/B,MAAK,OAAO;;CAIhB,uBAA8C;AAC5C,OAAK,OAAO"}
@@ -0,0 +1,13 @@
1
+ //#region src/util/log.d.ts
2
+ type LogLevel = "debug" | "info" | "warn" | "error" | "none";
3
+ declare function setLogLevel(level: LogLevel): void;
4
+ declare function getLogLevel(): LogLevel;
5
+ interface Logger {
6
+ debug(...args: unknown[]): void;
7
+ error(...args: unknown[]): void;
8
+ info(...args: unknown[]): void;
9
+ warn(...args: unknown[]): void;
10
+ }
11
+ declare function createLogger(scope: string): Logger;
12
+ //#endregion
13
+ export { LogLevel, Logger, createLogger, getLogLevel, setLogLevel };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.d.mts","names":[],"sources":["../../src/util/log.ts"],"mappings":";KAAY,QAAA;AAAA,iBAsBI,WAAA,CAAY,KAAA,EAAO,QAAA;AAAA,iBAInB,WAAA,CAAA,GAAe,QAAA;AAAA,UAKd,MAAA;EACf,KAAA,IAAS,IAAA;EACT,KAAA,IAAS,IAAA;EACT,IAAA,IAAQ,IAAA;EACR,IAAA,IAAQ,IAAA;AAAA;AAAA,iBAeM,YAAA,CAAa,KAAA,WAAgB,MAAA"}
@@ -0,0 +1,37 @@
1
+ //#region src/util/log.ts
2
+ const PRIORITY = {
3
+ debug: 0,
4
+ info: 1,
5
+ warn: 2,
6
+ error: 3,
7
+ none: 4
8
+ };
9
+ const CONSOLE_FN = {
10
+ debug: "debug",
11
+ info: "info",
12
+ warn: "warn",
13
+ error: "error"
14
+ };
15
+ let threshold = PRIORITY.warn;
16
+ function setLogLevel(level) {
17
+ threshold = PRIORITY[level];
18
+ }
19
+ function getLogLevel() {
20
+ return Object.entries(PRIORITY).find(([, v]) => v === threshold)?.[0] ?? "warn";
21
+ }
22
+ function emit(level, prefix, args) {
23
+ if (PRIORITY[level] < threshold) return;
24
+ const fn = CONSOLE_FN[level];
25
+ globalThis.console[fn](prefix, ...args);
26
+ }
27
+ function createLogger(scope) {
28
+ const prefix = `[Interfere:${scope}]`;
29
+ return {
30
+ debug: (...args) => emit("debug", prefix, args),
31
+ info: (...args) => emit("info", prefix, args),
32
+ warn: (...args) => emit("warn", prefix, args),
33
+ error: (...args) => emit("error", prefix, args)
34
+ };
35
+ }
36
+ //#endregion
37
+ export { createLogger, getLogLevel, setLogLevel };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.mjs","names":[],"sources":["../../src/util/log.ts"],"sourcesContent":["export type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\" | \"none\";\n\nconst PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n none: 4,\n};\n\nconst CONSOLE_FN: Record<\n Exclude<LogLevel, \"none\">,\n \"debug\" | \"info\" | \"warn\" | \"error\"\n> = {\n debug: \"debug\",\n info: \"info\",\n warn: \"warn\",\n error: \"error\",\n};\n\nlet threshold = PRIORITY.warn;\n\nexport function setLogLevel(level: LogLevel): void {\n threshold = PRIORITY[level];\n}\n\nexport function getLogLevel(): LogLevel {\n const entry = Object.entries(PRIORITY).find(([, v]) => v === threshold);\n return (entry?.[0] ?? \"warn\") as LogLevel;\n}\n\nexport interface Logger {\n debug(...args: unknown[]): void;\n error(...args: unknown[]): void;\n info(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n}\n\nfunction emit(\n level: Exclude<LogLevel, \"none\">,\n prefix: string,\n args: unknown[]\n): void {\n if (PRIORITY[level] < threshold) {\n return;\n }\n const fn = CONSOLE_FN[level];\n globalThis.console[fn](prefix, ...args);\n}\n\nexport function createLogger(scope: string): Logger {\n const prefix = `[Interfere:${scope}]`;\n return {\n debug: (...args) => emit(\"debug\", prefix, args),\n info: (...args) => emit(\"info\", prefix, args),\n warn: (...args) => emit(\"warn\", prefix, args),\n error: (...args) => emit(\"error\", prefix, args),\n };\n}\n"],"mappings":";AAEA,MAAM,WAAqC;CACzC,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;CACP,MAAM;CACP;AAED,MAAM,aAGF;CACF,OAAO;CACP,MAAM;CACN,MAAM;CACN,OAAO;CACR;AAED,IAAI,YAAY,SAAS;AAEzB,SAAgB,YAAY,OAAuB;AACjD,aAAY,SAAS;;AAGvB,SAAgB,cAAwB;AAEtC,QADc,OAAO,QAAQ,SAAS,CAAC,MAAM,GAAG,OAAO,MAAM,UAAU,GACvD,MAAM;;AAUxB,SAAS,KACP,OACA,QACA,MACM;AACN,KAAI,SAAS,SAAS,UACpB;CAEF,MAAM,KAAK,WAAW;AACtB,YAAW,QAAQ,IAAI,QAAQ,GAAG,KAAK;;AAGzC,SAAgB,aAAa,OAAuB;CAClD,MAAM,SAAS,cAAc,MAAM;AACnC,QAAO;EACL,QAAQ,GAAG,SAAS,KAAK,SAAS,QAAQ,KAAK;EAC/C,OAAO,GAAG,SAAS,KAAK,QAAQ,QAAQ,KAAK;EAC7C,OAAO,GAAG,SAAS,KAAK,QAAQ,QAAQ,KAAK;EAC7C,QAAQ,GAAG,SAAS,KAAK,SAAS,QAAQ,KAAK;EAChD"}
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "@interfere/react",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "0.1.0-alpha.25",
4
4
  "license": "MIT",
5
- "description": "Build apps that never break.",
5
+ "description": "Client-side React SDK for Interfere. Error tracking, session replay, and analytics.",
6
6
  "keywords": [
7
7
  "observability",
8
8
  "typescript",
9
9
  "react",
10
- "logging",
11
10
  "error-tracking",
12
11
  "session-replay"
13
12
  ],
@@ -16,91 +15,69 @@
16
15
  "url": "mailto:support@interfere.com"
17
16
  },
18
17
  "author": "Interfere <support@interfere.com> (https://interfere.com)",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/interfere-inc/interfere.git",
21
+ "directory": "src/packages/public/react-v2"
22
+ },
19
23
  "files": [
20
24
  "dist"
21
25
  ],
22
26
  "type": "module",
23
- "main": "./dist/index.mjs",
24
- "types": "./dist/index.d.mts",
25
- "typesVersions": {
26
- "*": {
27
- "server/*": [
28
- "dist/server/*.d.mts"
29
- ],
30
- "*": [
31
- "dist/*.d.mts"
32
- ]
33
- }
34
- },
35
27
  "exports": {
36
- "./provider": {
37
- "@source": "./src/provider.tsx",
38
- "types": "./dist/provider.d.mts",
39
- "default": "./dist/provider.mjs"
40
- },
41
- "./server/*": {
42
- "@source": "./src/server/*.ts",
43
- "types": "./dist/server/*.d.mts",
44
- "default": "./dist/server/*.mjs"
45
- },
46
- "./core/runtime/*": {
47
- "@source": "./src/core/runtime/*.ts",
48
- "types": "./dist/core/runtime/*.d.mts",
49
- "default": "./dist/core/runtime/*.mjs"
50
- },
51
- "./core/*": {
52
- "@source": "./src/core/*.ts",
53
- "types": "./dist/core/*.d.mts",
54
- "default": "./dist/core/*.mjs"
55
- },
56
28
  "./*": {
57
29
  "@source": "./src/*.ts",
58
30
  "types": "./dist/*.d.mts",
59
31
  "default": "./dist/*.mjs"
32
+ },
33
+ "./provider": {
34
+ "@source": "./src/provider.tsx",
35
+ "types": "./dist/provider.d.mts",
36
+ "default": "./dist/provider.mjs"
60
37
  }
61
38
  },
62
39
  "sideEffects": false,
63
40
  "publishConfig": {
64
41
  "access": "public"
65
42
  },
43
+ "scripts": {
44
+ "build": "tsdown",
45
+ "dev": "tsdown --watch",
46
+ "test:browser": "vitest run --project browser",
47
+ "test:unit": "vitest run --project unit --coverage",
48
+ "typecheck": "tsc --noEmit --incremental",
49
+ "test": "bun run test:unit && bun run test:browser"
50
+ },
66
51
  "dependencies": {
67
- "@effect/platform": "^0.94.1",
68
- "@rrweb/packer": "2.0.0-alpha.18",
69
- "@ua-parser-js/pro-enterprise": "^2.0.6",
70
- "effect": "^3.19.14",
71
- "nanoid": "^5.1.6",
72
- "rrweb": "2.0.0-alpha.18",
73
- "uuid": "^13.0.0",
74
- "zod": "^4.3.4",
75
- "@interfere/constants": "0.0.2-alpha.0",
76
- "@interfere/effect-utils": "0.0.2-alpha.0",
77
- "@interfere/types": "0.0.2-alpha.0"
52
+ "@fingerprintjs/fingerprintjs-pro": "catalog:",
53
+ "@interfere/constants": "workspace:*",
54
+ "@interfere/types": "workspace:*",
55
+ "@ua-parser-js/pro-enterprise": "catalog:",
56
+ "nanoid": "catalog:",
57
+ "rrweb": "catalog:",
58
+ "tctx": "catalog:",
59
+ "uuid": "catalog:"
78
60
  },
79
61
  "peerDependencies": {
80
- "react": ">=18",
81
- "react-dom": ">=18"
62
+ "react": ">=19",
63
+ "react-dom": ">=19"
82
64
  },
83
65
  "devDependencies": {
84
- "@rrweb/types": "2.0.0-alpha.18",
85
- "@types/node": "^22.19.3",
86
- "@types/react": "19.2.7",
87
- "@types/react-dom": "19.2.3",
88
- "@vitest/coverage-v8": "^4.0.16",
89
- "jsdom": "^27.4.0",
90
- "msw": "^2.12.7",
91
- "react": "^19.2.3",
92
- "react-dom": "^19.2.3",
93
- "tsdown": "^0.18.4",
94
- "typescript": "5.9.3",
95
- "vitest": "^4.0.16",
96
- "@interfere/test-utils": "0.0.0",
97
- "@interfere/typescript-config": "1.0.3-alpha.0",
98
- "@interfere/vitest-config": "1.0.1-alpha.0"
99
- },
100
- "scripts": {
101
- "build": "tsdown",
102
- "dev": "tsdown --watch",
103
- "typecheck": "tsc --noEmit --incremental",
104
- "test": "vitest run --coverage"
66
+ "@interfere/typescript-config": "workspace:*",
67
+ "@interfere/vitest-config": "workspace:*",
68
+ "@rrweb/types": "catalog:",
69
+ "@testing-library/react": "catalog:",
70
+ "@types/node": "catalog:",
71
+ "@types/react": "catalog:",
72
+ "@types/react-dom": "catalog:",
73
+ "@vitejs/plugin-react": "catalog:",
74
+ "@vitest/browser": "catalog:",
75
+ "@vitest/browser-playwright": "catalog:",
76
+ "@vitest/coverage-v8": "catalog:",
77
+ "jsdom": "catalog:",
78
+ "playwright": "catalog:",
79
+ "tsdown": "catalog:",
80
+ "typescript": "catalog:",
81
+ "vitest": "catalog:"
105
82
  }
106
- }
83
+ }
package/dist/client.d.mts DELETED
@@ -1,15 +0,0 @@
1
- import { SessionServiceTag } from "./effect/layers/session.layer.mjs";
2
- import { ConfigTag } from "./effect/tags.mjs";
3
- import { EventPayload } from "./core/events/event-registry.mjs";
4
- import { ValidationError } from "./effect/errors.mjs";
5
- import { ContextServiceTag } from "./effect/layers/context.layer.mjs";
6
- import { QueueServiceTag } from "./effect/layers/queue.layer.mjs";
7
- import { Effect } from "effect";
8
- import { EventType } from "@interfere/types/sdk/plugins/lib/types";
9
-
10
- //#region src/client.d.ts
11
- type CaptureFn = <T extends EventType>(type: T, payload: EventPayload<T>) => void;
12
- declare function captureEffect<T extends EventType>(type: T, payload: EventPayload<T>): Effect.Effect<void, ValidationError, QueueServiceTag | SessionServiceTag | ConfigTag | ContextServiceTag>;
13
- declare const capture: CaptureFn;
14
- //#endregion
15
- export { CaptureFn, capture, captureEffect };
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.d.mts","names":[],"sources":["../src/client.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;KAeY,SAAA,cAAuB,iBAC3B,YACG,aAAa;iBA0BR,wBAAwB,iBAChC,YACG,aAAa,KAAE,MAAA,CAAA,aAAA,iBAAA,kBAAA,iBAAA,GAAA,SAAA,GAAA;cAqFb,SAAS"}
package/dist/client.mjs DELETED
@@ -1,75 +0,0 @@
1
- import { dynamicRegistry } from "./core/events/event-registry.mjs";
2
- import { buildEnvelopeEffect } from "./effect/build-envelope.mjs";
3
- import { ValidationError } from "./effect/errors.mjs";
4
- import { ContextServiceTag } from "./effect/layers/context.layer.mjs";
5
- import { QueueServiceTag } from "./effect/layers/queue.layer.mjs";
6
- import { withSpan } from "./effect/layers/tracer.layer.mjs";
7
- import { forkWithSDK } from "./effect/runtime-services.mjs";
8
- import { Effect } from "effect";
9
-
10
- //#region src/client.ts
11
- function enrichPayload(basePayload, properties) {
12
- if (typeof basePayload === "object" && basePayload !== null) {
13
- const merged = {
14
- ...basePayload.properties ?? {},
15
- ...properties
16
- };
17
- return {
18
- ...basePayload,
19
- properties: merged
20
- };
21
- }
22
- return { properties };
23
- }
24
- function captureEffect(type, payload) {
25
- const handler = dynamicRegistry.get(type);
26
- if (!handler) return Effect.gen(function* () {
27
- const queue = yield* QueueServiceTag;
28
- const env = yield* buildEnvelopeEffect({
29
- type,
30
- payload
31
- });
32
- yield* queue.add(env);
33
- yield* Effect.logTrace("Captured event with no handler", {
34
- type,
35
- envelopeId: env.uuid,
36
- path: "fast"
37
- });
38
- }).pipe(Effect.withSpan("capture.fast", { attributes: { type } }));
39
- return Effect.gen(function* () {
40
- const queue = yield* QueueServiceTag;
41
- const context = yield* ContextServiceTag;
42
- const validated = yield* withSpan("capture.validate", Effect.sync(() => handler ? handler.schema.safeParse(payload) : {
43
- success: false,
44
- error: { issues: [{ message: "Missing handler" }] }
45
- }).pipe(Effect.flatMap((result) => result.success === true ? Effect.succeed(result.data) : Effect.fail(new ValidationError({
46
- message: "Invalid payload",
47
- payload,
48
- issues: result.error?.issues
49
- })))), { attributes: { type } });
50
- const transformed = handler && "transform" in handler && typeof handler.transform === "function" ? handler.transform(validated) : validated;
51
- const env = yield* buildEnvelopeEffect({
52
- type,
53
- payload: handler?.enrich === true ? yield* withSpan("capture.enrich", context.getOnce().pipe(Effect.map((properties) => enrichPayload(transformed, properties))), { attributes: { type } }) : transformed
54
- });
55
- yield* queue.add(env);
56
- yield* Effect.logTrace("Captured event with handler", {
57
- type,
58
- envelopeId: env.uuid
59
- });
60
- }).pipe(Effect.withSpan("capture.full", { attributes: { type } }));
61
- }
62
- const capture = (type, payload) => {
63
- if (typeof window === "undefined") return;
64
- forkWithSDK(captureEffect(type, payload).pipe(Effect.catchTag("ValidationError", (err) => Effect.logError("Invalid event payload", {
65
- type,
66
- payload,
67
- issues: err.issues
68
- })), Effect.catchAll((err) => Effect.logError("Failed to capture event", {
69
- type,
70
- error: String(err)
71
- }))));
72
- };
73
-
74
- //#endregion
75
- export { capture, captureEffect };
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.mjs","names":["capture: CaptureFn"],"sources":["../src/client.ts"],"sourcesContent":["import type { EventType } from \"@interfere/types/sdk/plugins/lib/types\";\n\nimport { Effect } from \"effect\";\n\nimport {\n dynamicRegistry,\n type EventPayload,\n} from \"./core/events/event-registry.js\";\nimport { buildEnvelopeEffect } from \"./effect/build-envelope.js\";\nimport { ValidationError } from \"./effect/errors.js\";\nimport { ContextServiceTag } from \"./effect/layers/context.layer.js\";\nimport { QueueServiceTag } from \"./effect/layers/queue.layer.js\";\nimport { withSpan } from \"./effect/layers/tracer.layer.js\";\nimport { forkWithSDK } from \"./effect/runtime-services.js\";\n\nexport type CaptureFn = <T extends EventType>(\n type: T,\n payload: EventPayload<T>\n) => void;\n\ntype EnrichedPayload<T> =\n T extends Record<string, unknown>\n ? T & { properties?: Record<string, unknown> }\n : { properties: Record<string, unknown> };\n\nfunction enrichPayload<T>(\n basePayload: T,\n properties: Record<string, unknown>\n): EnrichedPayload<T> {\n if (typeof basePayload === \"object\" && basePayload !== null) {\n const existing = (basePayload as EnrichedPayload<T>).properties;\n\n const merged = { ...(existing ?? {}), ...properties };\n\n return {\n ...basePayload,\n properties: merged,\n } as EnrichedPayload<T>;\n }\n\n return { properties } as EnrichedPayload<T>;\n}\n\nexport function captureEffect<T extends EventType>(\n type: T,\n payload: EventPayload<T>\n) {\n const handler = dynamicRegistry.get(type);\n\n if (!handler) {\n return Effect.gen(function* () {\n const queue = yield* QueueServiceTag;\n const env = yield* buildEnvelopeEffect({ type, payload });\n\n yield* queue.add(env);\n\n yield* Effect.logTrace(\"Captured event with no handler\", {\n type,\n envelopeId: env.uuid,\n path: \"fast\",\n });\n }).pipe(Effect.withSpan(\"capture.fast\", { attributes: { type } }));\n }\n\n return Effect.gen(function* () {\n const queue = yield* QueueServiceTag;\n const context = yield* ContextServiceTag;\n\n const validated = yield* withSpan(\n \"capture.validate\",\n Effect.sync(() =>\n handler\n ? handler.schema.safeParse(payload)\n : {\n success: false,\n error: { issues: [{ message: \"Missing handler\" }] },\n }\n ).pipe(\n Effect.flatMap((result) =>\n result.success === true\n ? Effect.succeed((result as { data: unknown }).data)\n : Effect.fail(\n new ValidationError({\n message: \"Invalid payload\",\n payload,\n issues: (result as { error?: { issues?: unknown } }).error\n ?.issues,\n })\n )\n )\n ),\n { attributes: { type } }\n );\n\n const transformed =\n handler &&\n \"transform\" in handler &&\n typeof handler.transform === \"function\"\n ? (handler.transform as (input: unknown) => unknown)(validated)\n : validated;\n\n const finalPayload =\n handler?.enrich === true\n ? yield* withSpan(\n \"capture.enrich\",\n context\n .getOnce()\n .pipe(\n Effect.map((properties) =>\n enrichPayload(transformed, properties)\n )\n ),\n { attributes: { type } }\n )\n : transformed;\n\n const env = yield* buildEnvelopeEffect({\n type,\n payload: finalPayload as EventPayload<T>,\n });\n\n yield* queue.add(env);\n\n yield* Effect.logTrace(\"Captured event with handler\", {\n type,\n envelopeId: env.uuid,\n });\n }).pipe(Effect.withSpan(\"capture.full\", { attributes: { type } }));\n}\n\nexport const capture: CaptureFn = <T extends EventType>(\n type: T,\n payload: EventPayload<T>\n) => {\n if (typeof window === \"undefined\") {\n return;\n }\n\n forkWithSDK(\n captureEffect(type, payload).pipe(\n Effect.catchTag(\"ValidationError\", (err) =>\n Effect.logError(\"Invalid event payload\", {\n type,\n payload,\n issues: err.issues,\n })\n ),\n Effect.catchAll((err) =>\n Effect.logError(\"Failed to capture event\", {\n type,\n error: String(err),\n })\n )\n )\n );\n};\n"],"mappings":";;;;;;;;;;AAyBA,SAAS,cACP,aACA,YACoB;AACpB,KAAI,OAAO,gBAAgB,YAAY,gBAAgB,MAAM;EAG3D,MAAM,SAAS;GAAE,GAFC,YAAmC,cAEpB,EAAE;GAAG,GAAG;GAAY;AAErD,SAAO;GACL,GAAG;GACH,YAAY;GACb;;AAGH,QAAO,EAAE,YAAY;;AAGvB,SAAgB,cACd,MACA,SACA;CACA,MAAM,UAAU,gBAAgB,IAAI,KAAK;AAEzC,KAAI,CAAC,QACH,QAAO,OAAO,IAAI,aAAa;EAC7B,MAAM,QAAQ,OAAO;EACrB,MAAM,MAAM,OAAO,oBAAoB;GAAE;GAAM;GAAS,CAAC;AAEzD,SAAO,MAAM,IAAI,IAAI;AAErB,SAAO,OAAO,SAAS,kCAAkC;GACvD;GACA,YAAY,IAAI;GAChB,MAAM;GACP,CAAC;GACF,CAAC,KAAK,OAAO,SAAS,gBAAgB,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC;AAGpE,QAAO,OAAO,IAAI,aAAa;EAC7B,MAAM,QAAQ,OAAO;EACrB,MAAM,UAAU,OAAO;EAEvB,MAAM,YAAY,OAAO,SACvB,oBACA,OAAO,WACL,UACI,QAAQ,OAAO,UAAU,QAAQ,GACjC;GACE,SAAS;GACT,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,mBAAmB,CAAC,EAAE;GACpD,CACN,CAAC,KACA,OAAO,SAAS,WACd,OAAO,YAAY,OACf,OAAO,QAAS,OAA6B,KAAK,GAClD,OAAO,KACL,IAAI,gBAAgB;GAClB,SAAS;GACT;GACA,QAAS,OAA4C,OACjD;GACL,CAAC,CACH,CACN,CACF,EACD,EAAE,YAAY,EAAE,MAAM,EAAE,CACzB;EAED,MAAM,cACJ,WACA,eAAe,WACf,OAAO,QAAQ,cAAc,aACxB,QAAQ,UAA0C,UAAU,GAC7D;EAiBN,MAAM,MAAM,OAAO,oBAAoB;GACrC;GACA,SAhBA,SAAS,WAAW,OAChB,OAAO,SACL,kBACA,QACG,SAAS,CACT,KACC,OAAO,KAAK,eACV,cAAc,aAAa,WAAW,CACvC,CACF,EACH,EAAE,YAAY,EAAE,MAAM,EAAE,CACzB,GACD;GAKL,CAAC;AAEF,SAAO,MAAM,IAAI,IAAI;AAErB,SAAO,OAAO,SAAS,+BAA+B;GACpD;GACA,YAAY,IAAI;GACjB,CAAC;GACF,CAAC,KAAK,OAAO,SAAS,gBAAgB,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC;;AAGpE,MAAaA,WACX,MACA,YACG;AACH,KAAI,OAAO,WAAW,YACpB;AAGF,aACE,cAAc,MAAM,QAAQ,CAAC,KAC3B,OAAO,SAAS,oBAAoB,QAClC,OAAO,SAAS,yBAAyB;EACvC;EACA;EACA,QAAQ,IAAI;EACb,CAAC,CACH,EACD,OAAO,UAAU,QACf,OAAO,SAAS,2BAA2B;EACzC;EACA,OAAO,OAAO,IAAI;EACnB,CAAC,CACH,CACF,CACF"}
@@ -1,23 +0,0 @@
1
- import { AnyEventDefinition, EventHandlerConfig, EventSchemas } from "./plugin-event-types.mjs";
2
- import { EventType } from "@interfere/types/sdk/plugins/lib/types";
3
- import { z } from "zod";
4
-
5
- //#region src/core/events/event-registry.d.ts
6
- type EventHandlerFor<T extends EventType> = T extends keyof EventSchemas ? EventHandlerConfig<EventSchemas[T]> : never;
7
- type EventPayload<T extends EventType> = T extends keyof EventSchemas ? z.infer<EventSchemas[T]> : never;
8
- declare function getEventHandler<T extends EventType>(type: T): EventHandlerFor<T> | undefined;
9
- declare function hasEventHandler(type: EventType): type is keyof EventSchemas;
10
- interface PluginEventHandler<T extends EventType = EventType> {
11
- eventType: T;
12
- handler: EventHandlerFor<T>;
13
- }
14
- declare class DynamicEventRegistry {
15
- private readonly dynamicHandlers;
16
- register<T extends EventType>(eventType: T, handler: EventHandlerFor<T>): void;
17
- registerDefinition(def: AnyEventDefinition): void;
18
- get<T extends EventType>(eventType: T): EventHandlerFor<T> | undefined;
19
- merge(handlers: PluginEventHandler[]): void;
20
- }
21
- declare const dynamicRegistry: DynamicEventRegistry;
22
- //#endregion
23
- export { DynamicEventRegistry, EventHandlerFor, EventPayload, PluginEventHandler, dynamicRegistry, getEventHandler, hasEventHandler };
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-registry.d.mts","names":[],"sources":["../../../src/core/events/event-registry.ts"],"sourcesContent":[],"mappings":";;;;;KAYY,0BAA0B,aAAa,gBAAgB,eAC/D,mBAAmB,aAAa;KAIxB,uBAAuB,aAAa,gBAAgB,eAC5D,CAAA,CAAE,MAAM,aAAa;AANb,iBAUI,eAVW,CAAA,UAUe,SAVf,CAAA,CAAA,IAAA,EAWnB,CAXmB,CAAA,EAYxB,eAZwB,CAYR,CAZQ,CAAA,GAAA,SAAA;AAAW,iBAkBtB,eAAA,CAlBsB,IAAA,EAkBA,SAlBA,CAAA,EAAA,IAAA,IAAA,MAkB0B,YAlB1B;AAAa,UAuBlC,kBAvBkC,CAAA,UAuBL,SAvBK,GAuBO,SAvBP,CAAA,CAAA;EAAgB,SAAA,EAwBtD,CAxBsD;EAC5C,OAAA,EAwBZ,eAxBY,CAwBI,CAxBJ,CAAA;;AAAnB,cA4BS,oBAAA,CA5BT;EAAkB,iBAAA,eAAA;EAIV,QAAA,CAAA,UA8BS,SA9BG,CAAA,CAAA,SAAA,EA+BT,CA/BS,EAAA,OAAA,EAgCX,eAhCW,CAgCK,CAhCL,CAAA,CAAA,EAAA,IAAA;EAAW,kBAAA,CAAA,GAAA,EAwCT,kBAxCS,CAAA,EAAA,IAAA;EAAa,GAAA,CAAA,UAgDhC,SAhDgC,CAAA,CAAA,SAAA,EAgDV,CAhDU,CAAA,EAgDN,eAhDM,CAgDU,CAhDV,CAAA,GAAA,SAAA;EAAgB,KAAA,CAAA,QAAA,EAuD9C,kBAvD8C,EAAA,CAAA,EAAA,IAAA;;AACvC,cA8DZ,eA9DY,EA8DG,oBA9DH"}
@@ -1,32 +0,0 @@
1
- import { eventSchemas } from "./plugin-event-types.mjs";
2
-
3
- //#region src/core/events/event-registry.ts
4
- function getEventHandler(type) {
5
- return dynamicRegistry.get(type);
6
- }
7
- function hasEventHandler(type) {
8
- return type in eventSchemas;
9
- }
10
- var DynamicEventRegistry = class {
11
- dynamicHandlers = /* @__PURE__ */ new Map();
12
- register(eventType, handler) {
13
- this.dynamicHandlers.set(eventType, handler);
14
- }
15
- registerDefinition(def) {
16
- this.dynamicHandlers.set(def.type, {
17
- schema: def.schema,
18
- enrich: def.enrich,
19
- transform: def.transform
20
- });
21
- }
22
- get(eventType) {
23
- return this.dynamicHandlers.get(eventType);
24
- }
25
- merge(handlers) {
26
- for (const { eventType, handler } of handlers) this.register(eventType, handler);
27
- }
28
- };
29
- const dynamicRegistry = new DynamicEventRegistry();
30
-
31
- //#endregion
32
- export { DynamicEventRegistry, dynamicRegistry, getEventHandler, hasEventHandler };
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-registry.mjs","names":[],"sources":["../../../src/core/events/event-registry.ts"],"sourcesContent":["import type { EventType } from \"@interfere/types/sdk/plugins/lib/types\";\n\nimport type { z } from \"zod\";\n\nimport {\n type AnyEventDefinition,\n type EventHandlerConfig,\n type EventSchemas,\n eventSchemas,\n} from \"./plugin-event-types.js\";\n\n// Type to get the handler for a specific event type\nexport type EventHandlerFor<T extends EventType> = T extends keyof EventSchemas\n ? EventHandlerConfig<EventSchemas[T]>\n : never;\n\n// Type to get the schema input type for an event\nexport type EventPayload<T extends EventType> = T extends keyof EventSchemas\n ? z.infer<EventSchemas[T]>\n : never;\n\n// Runtime helper to get handler with full type information\nexport function getEventHandler<T extends EventType>(\n type: T\n): EventHandlerFor<T> | undefined {\n // All events are now plugin-registered\n return dynamicRegistry.get(type);\n}\n\n// Type guard to check if an event type has a handler\nexport function hasEventHandler(type: EventType): type is keyof EventSchemas {\n return type in eventSchemas;\n}\n\n// Plugin registration system for dynamic event handlers\nexport interface PluginEventHandler<T extends EventType = EventType> {\n eventType: T;\n handler: EventHandlerFor<T>;\n}\n\n// Advanced type for plugin-provided event handlers\nexport class DynamicEventRegistry {\n private readonly dynamicHandlers = new Map<\n EventType,\n EventHandlerConfig<z.ZodType>\n >();\n\n register<T extends EventType>(\n eventType: T,\n handler: EventHandlerFor<T>\n ): void {\n this.dynamicHandlers.set(\n eventType,\n handler as EventHandlerConfig<z.ZodType>\n );\n }\n\n registerDefinition(def: AnyEventDefinition): void {\n this.dynamicHandlers.set(def.type, {\n schema: def.schema,\n enrich: def.enrich,\n transform: def.transform,\n } as EventHandlerConfig<z.ZodType>);\n }\n\n get<T extends EventType>(eventType: T): EventHandlerFor<T> | undefined {\n // Only check dynamic handlers since all events are plugin-registered\n return this.dynamicHandlers.get(eventType) as\n | EventHandlerFor<T>\n | undefined;\n }\n\n merge(handlers: PluginEventHandler[]): void {\n for (const { eventType, handler } of handlers) {\n this.register(eventType, handler);\n }\n }\n}\n\n// Export a singleton instance for the dynamic registry\nexport const dynamicRegistry = new DynamicEventRegistry();\n"],"mappings":";;;AAsBA,SAAgB,gBACd,MACgC;AAEhC,QAAO,gBAAgB,IAAI,KAAK;;AAIlC,SAAgB,gBAAgB,MAA6C;AAC3E,QAAO,QAAQ;;AAUjB,IAAa,uBAAb,MAAkC;CAChC,AAAiB,kCAAkB,IAAI,KAGpC;CAEH,SACE,WACA,SACM;AACN,OAAK,gBAAgB,IACnB,WACA,QACD;;CAGH,mBAAmB,KAA+B;AAChD,OAAK,gBAAgB,IAAI,IAAI,MAAM;GACjC,QAAQ,IAAI;GACZ,QAAQ,IAAI;GACZ,WAAW,IAAI;GAChB,CAAkC;;CAGrC,IAAyB,WAA8C;AAErE,SAAO,KAAK,gBAAgB,IAAI,UAAU;;CAK5C,MAAM,UAAsC;AAC1C,OAAK,MAAM,EAAE,WAAW,aAAa,SACnC,MAAK,SAAS,WAAW,QAAQ;;;AAMvC,MAAa,kBAAkB,IAAI,sBAAsB"}