@interfere/react 0.0.1 → 0.0.2-alpha.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.
Files changed (198) hide show
  1. package/dist/client.d.mts +15 -0
  2. package/dist/client.d.mts.map +1 -0
  3. package/dist/client.mjs +75 -0
  4. package/dist/client.mjs.map +1 -0
  5. package/dist/core/events/event-registry.d.mts +23 -0
  6. package/dist/core/events/event-registry.d.mts.map +1 -0
  7. package/dist/core/events/event-registry.mjs +32 -0
  8. package/dist/core/events/event-registry.mjs.map +1 -0
  9. package/dist/core/events/plugin-event-types.d.mts +92 -0
  10. package/dist/core/events/plugin-event-types.d.mts.map +1 -0
  11. package/dist/core/events/plugin-event-types.mjs +25 -0
  12. package/dist/core/events/plugin-event-types.mjs.map +1 -0
  13. package/dist/core/plugins/dom-utils.d.mts +9 -0
  14. package/dist/core/plugins/dom-utils.d.mts.map +1 -0
  15. package/dist/core/plugins/dom-utils.mjs +25 -0
  16. package/dist/core/plugins/dom-utils.mjs.map +1 -0
  17. package/dist/core/plugins/impl/ai-summary.d.mts +6 -0
  18. package/dist/core/plugins/impl/ai-summary.d.mts.map +1 -0
  19. package/dist/core/plugins/impl/ai-summary.mjs +122 -0
  20. package/dist/core/plugins/impl/ai-summary.mjs.map +1 -0
  21. package/dist/core/plugins/impl/errors.d.mts +9 -0
  22. package/dist/core/plugins/impl/errors.d.mts.map +1 -0
  23. package/dist/core/plugins/impl/errors.mjs +153 -0
  24. package/dist/core/plugins/impl/errors.mjs.map +1 -0
  25. package/dist/core/plugins/impl/page-events.d.mts +15 -0
  26. package/dist/core/plugins/impl/page-events.d.mts.map +1 -0
  27. package/dist/core/plugins/impl/page-events.mjs +131 -0
  28. package/dist/core/plugins/impl/page-events.mjs.map +1 -0
  29. package/dist/core/plugins/impl/rage-click.d.mts +6 -0
  30. package/dist/core/plugins/impl/rage-click.d.mts.map +1 -0
  31. package/dist/core/plugins/impl/rage-click.mjs +53 -0
  32. package/dist/core/plugins/impl/rage-click.mjs.map +1 -0
  33. package/dist/core/plugins/impl/replay.d.mts +9 -0
  34. package/dist/core/plugins/impl/replay.d.mts.map +1 -0
  35. package/dist/core/plugins/impl/replay.mjs +144 -0
  36. package/dist/core/plugins/impl/replay.mjs.map +1 -0
  37. package/dist/core/plugins/impl/server-tracing.d.mts +7 -0
  38. package/dist/core/plugins/impl/server-tracing.d.mts.map +1 -0
  39. package/dist/core/plugins/impl/server-tracing.mjs +160 -0
  40. package/dist/core/plugins/impl/server-tracing.mjs.map +1 -0
  41. package/dist/core/plugins/plugin-event-system.d.mts +47 -0
  42. package/dist/core/plugins/plugin-event-system.d.mts.map +1 -0
  43. package/dist/core/plugins/plugin-event-system.mjs +75 -0
  44. package/dist/core/plugins/plugin-event-system.mjs.map +1 -0
  45. package/dist/core/plugins/plugin-loader.d.mts +22 -0
  46. package/dist/core/plugins/plugin-loader.d.mts.map +1 -0
  47. package/dist/core/plugins/plugin-loader.mjs +142 -0
  48. package/dist/core/plugins/plugin-loader.mjs.map +1 -0
  49. package/dist/core/runtime/config.d.mts +14 -0
  50. package/dist/core/runtime/config.d.mts.map +1 -0
  51. package/dist/core/runtime/config.mjs +39 -0
  52. package/dist/core/runtime/config.mjs.map +1 -0
  53. package/dist/core/runtime/context.d.mts +25 -0
  54. package/dist/core/runtime/context.d.mts.map +1 -0
  55. package/dist/core/runtime/context.mjs +48 -0
  56. package/dist/core/runtime/context.mjs.map +1 -0
  57. package/dist/core/runtime/ingest-target.d.mts +10 -0
  58. package/dist/core/runtime/ingest-target.d.mts.map +1 -0
  59. package/dist/core/runtime/ingest-target.mjs +15 -0
  60. package/dist/core/runtime/ingest-target.mjs.map +1 -0
  61. package/dist/core/schemas.d.mts +85 -0
  62. package/dist/core/schemas.d.mts.map +1 -0
  63. package/dist/core/schemas.mjs +1 -0
  64. package/dist/effect/build-envelope.d.mts +9 -0
  65. package/dist/effect/build-envelope.d.mts.map +1 -0
  66. package/dist/effect/build-envelope.mjs +29 -0
  67. package/dist/effect/build-envelope.mjs.map +1 -0
  68. package/dist/effect/errors.d.mts +36 -0
  69. package/dist/effect/errors.d.mts.map +1 -0
  70. package/dist/effect/errors.mjs +10 -0
  71. package/dist/effect/errors.mjs.map +1 -0
  72. package/dist/effect/layers/config.layer.d.mts +13 -0
  73. package/dist/effect/layers/config.layer.d.mts.map +1 -0
  74. package/dist/effect/layers/config.layer.mjs +21 -0
  75. package/dist/effect/layers/config.layer.mjs.map +1 -0
  76. package/dist/effect/layers/context.layer.d.mts +12 -0
  77. package/dist/effect/layers/context.layer.d.mts.map +1 -0
  78. package/dist/effect/layers/context.layer.mjs +14 -0
  79. package/dist/effect/layers/context.layer.mjs.map +1 -0
  80. package/dist/effect/layers/http.layer.d.mts +21 -0
  81. package/dist/effect/layers/http.layer.d.mts.map +1 -0
  82. package/dist/effect/layers/http.layer.mjs +113 -0
  83. package/dist/effect/layers/http.layer.mjs.map +1 -0
  84. package/dist/effect/layers/queue.layer.d.mts +30 -0
  85. package/dist/effect/layers/queue.layer.d.mts.map +1 -0
  86. package/dist/effect/layers/queue.layer.mjs +232 -0
  87. package/dist/effect/layers/queue.layer.mjs.map +1 -0
  88. package/dist/effect/layers/session.layer.d.mts +26 -0
  89. package/dist/effect/layers/session.layer.d.mts.map +1 -0
  90. package/dist/effect/layers/session.layer.mjs +126 -0
  91. package/dist/effect/layers/session.layer.mjs.map +1 -0
  92. package/dist/effect/layers/storage.layer.d.mts +19 -0
  93. package/dist/effect/layers/storage.layer.d.mts.map +1 -0
  94. package/dist/effect/layers/storage.layer.mjs +200 -0
  95. package/dist/effect/layers/storage.layer.mjs.map +1 -0
  96. package/dist/effect/layers/tracer.layer.d.mts +9 -0
  97. package/dist/effect/layers/tracer.layer.d.mts.map +1 -0
  98. package/dist/effect/layers/tracer.layer.mjs +11 -0
  99. package/dist/effect/layers/tracer.layer.mjs.map +1 -0
  100. package/dist/effect/runtime-services.d.mts +22 -0
  101. package/dist/effect/runtime-services.d.mts.map +1 -0
  102. package/dist/effect/runtime-services.mjs +76 -0
  103. package/dist/effect/runtime-services.mjs.map +1 -0
  104. package/dist/effect/tags.d.mts +50 -0
  105. package/dist/effect/tags.d.mts.map +1 -0
  106. package/dist/effect/tags.mjs +7 -0
  107. package/dist/effect/tags.mjs.map +1 -0
  108. package/dist/hooks/use-runtime-and-plugins.d.mts +7 -0
  109. package/dist/hooks/use-runtime-and-plugins.d.mts.map +1 -0
  110. package/dist/hooks/use-runtime-and-plugins.mjs +153 -0
  111. package/dist/hooks/use-runtime-and-plugins.mjs.map +1 -0
  112. package/dist/hooks/use-session.d.mts +40 -0
  113. package/dist/hooks/use-session.d.mts.map +1 -0
  114. package/dist/hooks/use-session.mjs +96 -0
  115. package/dist/hooks/use-session.mjs.map +1 -0
  116. package/dist/package.mjs +100 -0
  117. package/dist/package.mjs.map +1 -0
  118. package/dist/provider.d.mts +17 -0
  119. package/dist/provider.d.mts.map +1 -0
  120. package/dist/provider.mjs +26 -0
  121. package/dist/provider.mjs.map +1 -0
  122. package/dist/server/auth.d.mts +11 -0
  123. package/dist/server/auth.d.mts.map +1 -0
  124. package/dist/server/auth.mjs +36 -0
  125. package/dist/server/auth.mjs.map +1 -0
  126. package/dist/server/capture.d.mts +18 -0
  127. package/dist/server/capture.d.mts.map +1 -0
  128. package/dist/server/capture.mjs +105 -0
  129. package/dist/server/capture.mjs.map +1 -0
  130. package/package.json +60 -27
  131. package/dist/__tests__/client.test.d.ts +0 -2
  132. package/dist/__tests__/client.test.d.ts.map +0 -1
  133. package/dist/__tests__/client.test.js +0 -447
  134. package/dist/__tests__/client.test.js.map +0 -1
  135. package/dist/__tests__/lib/core/error-handlers.test.d.ts +0 -2
  136. package/dist/__tests__/lib/core/error-handlers.test.d.ts.map +0 -1
  137. package/dist/__tests__/lib/core/error-handlers.test.js +0 -596
  138. package/dist/__tests__/lib/core/error-handlers.test.js.map +0 -1
  139. package/dist/__tests__/lib/core/event-queue.test.d.ts +0 -2
  140. package/dist/__tests__/lib/core/event-queue.test.d.ts.map +0 -1
  141. package/dist/__tests__/lib/core/event-queue.test.js +0 -290
  142. package/dist/__tests__/lib/core/event-queue.test.js.map +0 -1
  143. package/dist/__tests__/lib/core/runtime.test.d.ts +0 -2
  144. package/dist/__tests__/lib/core/runtime.test.d.ts.map +0 -1
  145. package/dist/__tests__/lib/core/runtime.test.js +0 -133
  146. package/dist/__tests__/lib/core/runtime.test.js.map +0 -1
  147. package/dist/__tests__/lib/core/session-manager.test.d.ts +0 -2
  148. package/dist/__tests__/lib/core/session-manager.test.d.ts.map +0 -1
  149. package/dist/__tests__/lib/core/session-manager.test.js +0 -356
  150. package/dist/__tests__/lib/core/session-manager.test.js.map +0 -1
  151. package/dist/__tests__/provider.test.d.ts +0 -2
  152. package/dist/__tests__/provider.test.d.ts.map +0 -1
  153. package/dist/__tests__/provider.test.js +0 -143
  154. package/dist/__tests__/provider.test.js.map +0 -1
  155. package/dist/client.d.ts +0 -78
  156. package/dist/client.d.ts.map +0 -1
  157. package/dist/client.js +0 -219
  158. package/dist/client.js.map +0 -1
  159. package/dist/index.d.ts +0 -6
  160. package/dist/index.d.ts.map +0 -1
  161. package/dist/index.js +0 -5
  162. package/dist/index.js.map +0 -1
  163. package/dist/lib/core/error-handlers.d.ts +0 -14
  164. package/dist/lib/core/error-handlers.d.ts.map +0 -1
  165. package/dist/lib/core/error-handlers.js +0 -191
  166. package/dist/lib/core/error-handlers.js.map +0 -1
  167. package/dist/lib/core/event-queue.d.ts +0 -90
  168. package/dist/lib/core/event-queue.d.ts.map +0 -1
  169. package/dist/lib/core/event-queue.js +0 -286
  170. package/dist/lib/core/event-queue.js.map +0 -1
  171. package/dist/lib/core/runtime.d.ts +0 -7
  172. package/dist/lib/core/runtime.d.ts.map +0 -1
  173. package/dist/lib/core/runtime.js +0 -16
  174. package/dist/lib/core/runtime.js.map +0 -1
  175. package/dist/lib/core/session-manager.d.ts +0 -96
  176. package/dist/lib/core/session-manager.d.ts.map +0 -1
  177. package/dist/lib/core/session-manager.js +0 -431
  178. package/dist/lib/core/session-manager.js.map +0 -1
  179. package/dist/lib/persistence/storage.d.ts +0 -5
  180. package/dist/lib/persistence/storage.d.ts.map +0 -1
  181. package/dist/lib/persistence/storage.js +0 -67
  182. package/dist/lib/persistence/storage.js.map +0 -1
  183. package/dist/lib/session/rage-click.d.ts +0 -2
  184. package/dist/lib/session/rage-click.d.ts.map +0 -1
  185. package/dist/lib/session/rage-click.js +0 -51
  186. package/dist/lib/session/rage-click.js.map +0 -1
  187. package/dist/lib/session/replay.d.ts +0 -3
  188. package/dist/lib/session/replay.d.ts.map +0 -1
  189. package/dist/lib/session/replay.js +0 -106
  190. package/dist/lib/session/replay.js.map +0 -1
  191. package/dist/lib/session/session-summary.d.ts +0 -3
  192. package/dist/lib/session/session-summary.d.ts.map +0 -1
  193. package/dist/lib/session/session-summary.js +0 -79
  194. package/dist/lib/session/session-summary.js.map +0 -1
  195. package/dist/provider.d.ts +0 -76
  196. package/dist/provider.d.ts.map +0 -1
  197. package/dist/provider.js +0 -138
  198. package/dist/provider.js.map +0 -1
@@ -0,0 +1,40 @@
1
+ //#region src/hooks/use-session.d.ts
2
+ /**
3
+ * React hook to get the current session ID.
4
+ * Automatically handles cleanup on unmount.
5
+ *
6
+ * @returns Object with sessionId (string | null) and loading state
7
+ *
8
+ * @example
9
+ * function MyComponent() {
10
+ * const { sessionId, loading, error } = useSession();
11
+ *
12
+ * if (loading) return <div>Loading session...</div>;
13
+ * if (error) return <div>Error: {error.message}</div>;
14
+ *
15
+ * return <div>Session ID: {sessionId}</div>;
16
+ * }
17
+ */
18
+ declare function useSession(): {
19
+ sessionId: string | null;
20
+ loading: boolean;
21
+ error: Error | null;
22
+ };
23
+ /**
24
+ * React hook to execute a callback when the session is ready.
25
+ * Automatically handles cleanup on unmount.
26
+ *
27
+ * @param callback Function to call with the session ID
28
+ * @param deps Dependency array for the callback
29
+ *
30
+ * @example
31
+ * function MyComponent() {
32
+ * useSessionReady((sessionId) => {
33
+ * console.log('Session is ready:', sessionId);
34
+ * // Send analytics event, initialize tracking, etc.
35
+ * }, []);
36
+ * }
37
+ */
38
+ declare function useSessionReady(callback: (sessionId: string) => void, deps?: React.DependencyList): void;
39
+ //#endregion
40
+ export { useSession, useSessionReady };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-session.d.mts","names":[],"sources":["../../src/hooks/use-session.ts"],"sourcesContent":[],"mappings":";;AAsBA;AA2EA;;;;;;;;;;;;;;iBA3EgB,UAAA,CAAA;;;SAAU;;;;;;;;;;;;;;;;;iBA2EV,eAAA,+CAER,KAAA,CAAM"}
@@ -0,0 +1,96 @@
1
+ import { SessionServiceTag } from "../effect/layers/session.layer.mjs";
2
+ import { runWithSDK } from "../effect/runtime-services.mjs";
3
+ import { Effect, Option } from "effect";
4
+ import { useEffect, useState } from "react";
5
+
6
+ //#region src/hooks/use-session.ts
7
+ /**
8
+ * React hook to get the current session ID.
9
+ * Automatically handles cleanup on unmount.
10
+ *
11
+ * @returns Object with sessionId (string | null) and loading state
12
+ *
13
+ * @example
14
+ * function MyComponent() {
15
+ * const { sessionId, loading, error } = useSession();
16
+ *
17
+ * if (loading) return <div>Loading session...</div>;
18
+ * if (error) return <div>Error: {error.message}</div>;
19
+ *
20
+ * return <div>Session ID: {sessionId}</div>;
21
+ * }
22
+ */
23
+ function useSession() {
24
+ const [sessionId, setSessionId] = useState(null);
25
+ const [loading, setLoading] = useState(true);
26
+ const [error, setError] = useState(null);
27
+ useEffect(() => {
28
+ runWithSDK(Effect.gen(function* () {
29
+ const sidOpt = yield* (yield* SessionServiceTag).getSessionId();
30
+ if (Option.isSome(sidOpt)) {
31
+ setSessionId(sidOpt.value);
32
+ setLoading(false);
33
+ return true;
34
+ }
35
+ return false;
36
+ })).then((has) => {
37
+ if (has) return;
38
+ });
39
+ const controller = new AbortController();
40
+ runWithSDK(Effect.gen(function* () {
41
+ return yield* (yield* SessionServiceTag).whenSessionReady({
42
+ signal: controller.signal,
43
+ timeout: 3e4
44
+ });
45
+ })).then((id) => {
46
+ setSessionId(id);
47
+ setLoading(false);
48
+ }).catch((err) => {
49
+ if (!controller.signal.aborted) {
50
+ setError(err instanceof Error ? err : new Error(String(err)));
51
+ setLoading(false);
52
+ }
53
+ });
54
+ return () => {
55
+ controller.abort();
56
+ };
57
+ }, []);
58
+ return {
59
+ sessionId,
60
+ loading,
61
+ error
62
+ };
63
+ }
64
+ /**
65
+ * React hook to execute a callback when the session is ready.
66
+ * Automatically handles cleanup on unmount.
67
+ *
68
+ * @param callback Function to call with the session ID
69
+ * @param deps Dependency array for the callback
70
+ *
71
+ * @example
72
+ * function MyComponent() {
73
+ * useSessionReady((sessionId) => {
74
+ * console.log('Session is ready:', sessionId);
75
+ * // Send analytics event, initialize tracking, etc.
76
+ * }, []);
77
+ * }
78
+ */
79
+ function useSessionReady(callback, deps = []) {
80
+ useEffect(() => {
81
+ const controller = new AbortController();
82
+ runWithSDK(Effect.gen(function* () {
83
+ return yield* (yield* SessionServiceTag).whenSessionReady({ signal: controller.signal });
84
+ })).then((sessionId) => {
85
+ if (!controller.signal.aborted) callback(sessionId);
86
+ }).catch((err) => {
87
+ if (!controller.signal.aborted) runWithSDK(Effect.logError("Failed to get session", { error: String(err) }));
88
+ });
89
+ return () => {
90
+ controller.abort();
91
+ };
92
+ }, deps);
93
+ }
94
+
95
+ //#endregion
96
+ export { useSession, useSessionReady };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-session.mjs","names":[],"sources":["../../src/hooks/use-session.ts"],"sourcesContent":["import { Effect, Option } from \"effect\";\nimport { useEffect, useState } from \"react\";\n\nimport { SessionServiceTag } from \"../effect/layers/session.layer.js\";\nimport { runWithSDK } from \"../effect/runtime-services.js\";\n\n/**\n * React hook to get the current session ID.\n * Automatically handles cleanup on unmount.\n *\n * @returns Object with sessionId (string | null) and loading state\n *\n * @example\n * function MyComponent() {\n * const { sessionId, loading, error } = useSession();\n *\n * if (loading) return <div>Loading session...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n *\n * return <div>Session ID: {sessionId}</div>;\n * }\n */\nexport function useSession() {\n const [sessionId, setSessionId] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n // Check if session already exists\n // Try to read session id from SessionService\n runWithSDK(\n Effect.gen(function* () {\n const session = yield* SessionServiceTag;\n const sidOpt = yield* session.getSessionId();\n if (Option.isSome(sidOpt)) {\n setSessionId(sidOpt.value);\n setLoading(false);\n return true as const;\n }\n return false as const;\n })\n ).then((has) => {\n if (has) {\n return;\n }\n });\n\n // Create AbortController for cleanup\n const controller = new AbortController();\n\n // Wait for session to be ready\n runWithSDK(\n Effect.gen(function* () {\n const session = yield* SessionServiceTag;\n const sid = yield* session.whenSessionReady({\n signal: controller.signal,\n timeout: 30_000,\n });\n return sid;\n })\n )\n .then((id) => {\n setSessionId(id);\n setLoading(false);\n })\n .catch((err) => {\n // Only set error if not aborted (aborted = component unmounted)\n if (!controller.signal.aborted) {\n setError(err instanceof Error ? err : new Error(String(err)));\n setLoading(false);\n }\n });\n\n // Cleanup function - abort the polling on unmount\n return () => {\n controller.abort();\n };\n }, []);\n\n return { sessionId, loading, error };\n}\n\n/**\n * React hook to execute a callback when the session is ready.\n * Automatically handles cleanup on unmount.\n *\n * @param callback Function to call with the session ID\n * @param deps Dependency array for the callback\n *\n * @example\n * function MyComponent() {\n * useSessionReady((sessionId) => {\n * console.log('Session is ready:', sessionId);\n * // Send analytics event, initialize tracking, etc.\n * }, []);\n * }\n */\nexport function useSessionReady(\n callback: (sessionId: string) => void,\n deps: React.DependencyList = []\n) {\n useEffect(() => {\n const controller = new AbortController();\n\n runWithSDK(\n Effect.gen(function* () {\n const session = yield* SessionServiceTag;\n const sid = yield* session.whenSessionReady({\n signal: controller.signal,\n });\n return sid;\n })\n )\n .then((sessionId: string) => {\n if (!controller.signal.aborted) {\n callback(sessionId);\n }\n })\n .catch((err: unknown) => {\n // Silently ignore abort errors (component unmounted)\n if (!controller.signal.aborted) {\n // biome-ignore lint/complexity/noVoid: necessary to avoid blocking\n void runWithSDK(\n Effect.logError(\"Failed to get session\", {\n error: String(err),\n })\n );\n }\n });\n\n return () => {\n controller.abort();\n };\n // biome-ignore lint/correctness/useExhaustiveDependencies: we want to pass the deps to the effect\n }, deps);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,aAAa;CAC3B,MAAM,CAAC,WAAW,gBAAgB,SAAwB,KAAK;CAC/D,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;CAC5C,MAAM,CAAC,OAAO,YAAY,SAAuB,KAAK;AAEtD,iBAAgB;AAGd,aACE,OAAO,IAAI,aAAa;GAEtB,MAAM,SAAS,QADC,OAAO,mBACO,cAAc;AAC5C,OAAI,OAAO,OAAO,OAAO,EAAE;AACzB,iBAAa,OAAO,MAAM;AAC1B,eAAW,MAAM;AACjB,WAAO;;AAET,UAAO;IACP,CACH,CAAC,MAAM,QAAQ;AACd,OAAI,IACF;IAEF;EAGF,MAAM,aAAa,IAAI,iBAAiB;AAGxC,aACE,OAAO,IAAI,aAAa;AAMtB,UAJY,QADI,OAAO,mBACI,iBAAiB;IAC1C,QAAQ,WAAW;IACnB,SAAS;IACV,CAAC;IAEF,CACH,CACE,MAAM,OAAO;AACZ,gBAAa,GAAG;AAChB,cAAW,MAAM;IACjB,CACD,OAAO,QAAQ;AAEd,OAAI,CAAC,WAAW,OAAO,SAAS;AAC9B,aAAS,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC,CAAC;AAC7D,eAAW,MAAM;;IAEnB;AAGJ,eAAa;AACX,cAAW,OAAO;;IAEnB,EAAE,CAAC;AAEN,QAAO;EAAE;EAAW;EAAS;EAAO;;;;;;;;;;;;;;;;;AAkBtC,SAAgB,gBACd,UACA,OAA6B,EAAE,EAC/B;AACA,iBAAgB;EACd,MAAM,aAAa,IAAI,iBAAiB;AAExC,aACE,OAAO,IAAI,aAAa;AAKtB,UAHY,QADI,OAAO,mBACI,iBAAiB,EAC1C,QAAQ,WAAW,QACpB,CAAC;IAEF,CACH,CACE,MAAM,cAAsB;AAC3B,OAAI,CAAC,WAAW,OAAO,QACrB,UAAS,UAAU;IAErB,CACD,OAAO,QAAiB;AAEvB,OAAI,CAAC,WAAW,OAAO,QAErB,CAAK,WACH,OAAO,SAAS,yBAAyB,EACvC,OAAO,OAAO,IAAI,EACnB,CAAC,CACH;IAEH;AAEJ,eAAa;AACX,cAAW,OAAO;;IAGnB,KAAK"}
@@ -0,0 +1,100 @@
1
+ //#region package.json
2
+ var name = "@interfere/react";
3
+ var version = "0.0.2-alpha.1";
4
+ var package_default = {
5
+ name,
6
+ version,
7
+ license: "MIT",
8
+ description: "Build apps that never break.",
9
+ keywords: [
10
+ "observability",
11
+ "typescript",
12
+ "react",
13
+ "logging",
14
+ "error-tracking",
15
+ "session-replay"
16
+ ],
17
+ homepage: "https://interfere.com",
18
+ bugs: { "url": "mailto:support@interfere.com" },
19
+ author: "Interfere <support@interfere.com> (https://interfere.com)",
20
+ files: ["dist"],
21
+ type: "module",
22
+ main: "./dist/index.mjs",
23
+ types: "./dist/index.d.mts",
24
+ typesVersions: { "*": {
25
+ "server/*": ["dist/server/*.d.mts"],
26
+ "*": ["dist/*.d.mts"]
27
+ } },
28
+ exports: {
29
+ "./provider": {
30
+ "@source": "./src/provider.tsx",
31
+ "types": "./dist/provider.d.mts",
32
+ "default": "./dist/provider.mjs"
33
+ },
34
+ "./server/*": {
35
+ "@source": "./src/server/*.ts",
36
+ "types": "./dist/server/*.d.mts",
37
+ "default": "./dist/server/*.mjs"
38
+ },
39
+ "./core/runtime/*": {
40
+ "@source": "./src/core/runtime/*.ts",
41
+ "types": "./dist/core/runtime/*.d.mts",
42
+ "default": "./dist/core/runtime/*.mjs"
43
+ },
44
+ "./core/*": {
45
+ "@source": "./src/core/*.ts",
46
+ "types": "./dist/core/*.d.mts",
47
+ "default": "./dist/core/*.mjs"
48
+ },
49
+ "./*": {
50
+ "@source": "./src/*.ts",
51
+ "types": "./dist/*.d.mts",
52
+ "default": "./dist/*.mjs"
53
+ }
54
+ },
55
+ sideEffects: false,
56
+ publishConfig: { "access": "public" },
57
+ scripts: {
58
+ "build": "tsdown",
59
+ "dev": "tsdown --watch",
60
+ "typecheck": "tsc --noEmit --incremental",
61
+ "test": "vitest run --coverage"
62
+ },
63
+ dependencies: {
64
+ "@effect/platform": "catalog:",
65
+ "@interfere/constants": "workspace:*",
66
+ "@interfere/effect-utils": "workspace:*",
67
+ "@interfere/types": "workspace:*",
68
+ "@rrweb/packer": "catalog:",
69
+ "@ua-parser-js/pro-enterprise": "catalog:",
70
+ "effect": "catalog:",
71
+ "nanoid": "catalog:",
72
+ "rrweb": "catalog:",
73
+ "uuid": "catalog:",
74
+ "zod": "catalog:"
75
+ },
76
+ peerDependencies: {
77
+ "react": ">=18",
78
+ "react-dom": ">=18"
79
+ },
80
+ devDependencies: {
81
+ "@interfere/test-utils": "workspace:*",
82
+ "@interfere/typescript-config": "workspace:*",
83
+ "@interfere/vitest-config": "workspace:*",
84
+ "@rrweb/types": "catalog:",
85
+ "@types/node": "catalog:",
86
+ "@types/react": "catalog:",
87
+ "@types/react-dom": "catalog:",
88
+ "@vitest/coverage-v8": "catalog:",
89
+ "jsdom": "catalog:",
90
+ "msw": "catalog:",
91
+ "react": "catalog:",
92
+ "react-dom": "catalog:",
93
+ "tsdown": "catalog:",
94
+ "typescript": "catalog:",
95
+ "vitest": "catalog:"
96
+ }
97
+ };
98
+
99
+ //#endregion
100
+ export { package_default as default, name, version };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.mjs","names":[],"sources":["../package.json"],"sourcesContent":[""],"mappings":""}
@@ -0,0 +1,17 @@
1
+ import { InterfereProviderValue, Plugin } from "./core/schemas.mjs";
2
+ import { Config } from "@interfere/types/sdk/config";
3
+ import { PropsWithChildren, ReactNode } from "react";
4
+
5
+ //#region src/provider.d.ts
6
+ interface InterfereProviderProps extends PropsWithChildren {
7
+ config: Config;
8
+ plugins?: Plugin[];
9
+ }
10
+ declare function InterfereProvider({
11
+ children,
12
+ config,
13
+ plugins
14
+ }: InterfereProviderProps): ReactNode;
15
+ declare function useInterfere(): InterfereProviderValue;
16
+ //#endregion
17
+ export { InterfereProvider, InterfereProviderProps, useInterfere };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.mts","names":[],"sources":["../src/provider.tsx"],"sourcesContent":[],"mappings":";;;;;UAwBiB,sBAAA,SAA+B;UACtC;EADO,OAAA,CAAA,EAEL,MAFK,EAAA;;AAEL,iBAGI,iBAAA,CAHJ;EAAA,QAAA;EAAA,MAAA;EAAA;AAAA,CAAA,EAOT,sBAPS,CAAA,EAOgB,SAPhB;AAFoC,iBA2BhC,YAAA,CAAA,CA3BgC,EA2BhB,sBA3BgB"}
@@ -0,0 +1,26 @@
1
+ "use client";
2
+
3
+ import { capture } from "./client.mjs";
4
+ import { useRuntimeAndPlugins } from "./hooks/use-runtime-and-plugins.mjs";
5
+ import { createContext, useContext, useMemo } from "react";
6
+ import { jsx } from "react/jsx-runtime";
7
+
8
+ //#region src/provider.tsx
9
+ const InterfereContext = createContext({ capture });
10
+ function InterfereProvider({ children, config, plugins }) {
11
+ const pluginApis = useRuntimeAndPlugins(config, plugins);
12
+ const contextValue = useMemo(() => ({
13
+ capture,
14
+ ...pluginApis
15
+ }), [pluginApis]);
16
+ return /* @__PURE__ */ jsx(InterfereContext.Provider, {
17
+ value: contextValue,
18
+ children
19
+ });
20
+ }
21
+ function useInterfere() {
22
+ return useContext(InterfereContext);
23
+ }
24
+
25
+ //#endregion
26
+ export { InterfereProvider, useInterfere };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.mjs","names":[],"sources":["../src/provider.tsx"],"sourcesContent":["\"use client\";\n\nimport type { Config } from \"@interfere/types/sdk/config\";\n\nimport {\n createContext,\n type PropsWithChildren,\n type ReactNode,\n useContext,\n useMemo,\n} from \"react\";\n\nimport { capture } from \"./client.js\";\nimport type { InterfereProviderValue, Plugin } from \"./core/schemas.js\";\nimport { useRuntimeAndPlugins } from \"./hooks/use-runtime-and-plugins.js\";\n\nconst interfereContextDefaultValue: InterfereProviderValue = {\n capture,\n};\n\nconst InterfereContext = createContext<InterfereProviderValue>(\n interfereContextDefaultValue\n);\n\nexport interface InterfereProviderProps extends PropsWithChildren {\n config: Config;\n plugins?: Plugin[];\n}\n\nexport function InterfereProvider({\n children,\n config,\n plugins,\n}: InterfereProviderProps): ReactNode {\n const pluginApis = useRuntimeAndPlugins(config, plugins);\n\n const contextValue = useMemo(\n () => ({\n capture,\n ...pluginApis,\n }),\n [pluginApis]\n );\n\n return (\n <InterfereContext.Provider value={contextValue}>\n {children}\n </InterfereContext.Provider>\n );\n}\n\nexport function useInterfere(): InterfereProviderValue {\n const context = useContext(InterfereContext);\n\n return context;\n}\n"],"mappings":";;;;;;;;AAoBA,MAAM,mBAAmB,cAJoC,EAC3D,SACD,CAIA;AAOD,SAAgB,kBAAkB,EAChC,UACA,QACA,WACoC;CACpC,MAAM,aAAa,qBAAqB,QAAQ,QAAQ;CAExD,MAAM,eAAe,eACZ;EACL;EACA,GAAG;EACJ,GACD,CAAC,WAAW,CACb;AAED,QACE,oBAAC,iBAAiB;EAAS,OAAO;EAC/B;GACyB;;AAIhC,SAAgB,eAAuC;AAGrD,QAFgB,WAAW,iBAAiB"}
@@ -0,0 +1,11 @@
1
+ //#region src/server/auth.d.ts
2
+ type FetchImpl = typeof fetch;
3
+ declare function exchangeSecretForPublicToken(apiUrl: string, secret: string, fetchImpl?: FetchImpl): Promise<string | null>;
4
+ declare function getPublicToken(params: {
5
+ apiUrl: string;
6
+ secret: string;
7
+ cacheTtlMs?: number;
8
+ fetchImpl?: FetchImpl;
9
+ }): Promise<string | null>;
10
+ //#endregion
11
+ export { exchangeSecretForPublicToken, getPublicToken };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.mts","names":[],"sources":["../../src/server/auth.ts"],"sourcesContent":[],"mappings":";KAAK,SAAA,UAAmB;AAAnB,iBAMiB,4BAAA,CANO,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,SAAA,CAAA,EAShB,SATgB,CAAA,EAU1B,OAV0B,CAAA,MAAA,GAAA,IAAA,CAAA;AAMP,iBAkCA,cAAA,CAlC4B,MAAA,EAGrC;EA+BS,MAAA,EAAA,MAAA;;;cAIR;IACV"}
@@ -0,0 +1,36 @@
1
+ //#region src/server/auth.ts
2
+ async function exchangeSecretForPublicToken(apiUrl, secret, fetchImpl = fetch) {
3
+ const res = await fetchImpl(`${apiUrl}/auth/exchange`, {
4
+ method: "POST",
5
+ headers: {
6
+ Authorization: `Bearer ${secret}`,
7
+ "Content-Type": "application/json"
8
+ }
9
+ });
10
+ if (!res.ok) return null;
11
+ const data = await res.json();
12
+ if (typeof data.publicToken === "string" && data.publicToken.length > 0) return data.publicToken;
13
+ return null;
14
+ }
15
+ const tokenCache = /* @__PURE__ */ new Map();
16
+ function getCacheKey(apiUrl, secret) {
17
+ return `${apiUrl}::${secret}`;
18
+ }
19
+ async function getPublicToken(params) {
20
+ const { apiUrl, secret, cacheTtlMs = 36e5, fetchImpl = fetch } = params;
21
+ const now = Date.now();
22
+ const cacheKey = getCacheKey(apiUrl, secret);
23
+ const cached = tokenCache.get(cacheKey);
24
+ if (cached && cached.expiresAt > now) return cached.token;
25
+ const token = await exchangeSecretForPublicToken(apiUrl, secret, fetchImpl);
26
+ if (!token) return null;
27
+ tokenCache.set(cacheKey, {
28
+ token,
29
+ expiresAt: now + cacheTtlMs
30
+ });
31
+ for (const [key, value] of tokenCache.entries()) if (value.expiresAt <= now) tokenCache.delete(key);
32
+ return token;
33
+ }
34
+
35
+ //#endregion
36
+ export { exchangeSecretForPublicToken, getPublicToken };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.mjs","names":[],"sources":["../../src/server/auth.ts"],"sourcesContent":["type FetchImpl = typeof fetch;\n\ninterface ExchangeResponse {\n publicToken: string;\n}\n\nexport async function exchangeSecretForPublicToken(\n apiUrl: string,\n secret: string,\n fetchImpl: FetchImpl = fetch\n): Promise<string | null> {\n const res = await fetchImpl(`${apiUrl}/auth/exchange`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${secret}`,\n \"Content-Type\": \"application/json\",\n },\n });\n\n if (!res.ok) {\n return null;\n }\n\n const data = (await res.json()) as Partial<ExchangeResponse>;\n if (typeof data.publicToken === \"string\" && data.publicToken.length > 0) {\n return data.publicToken;\n }\n\n return null;\n}\n\n// Use a Map to cache tokens keyed by apiUrl + secret to prevent token leakage between different configurations\nconst tokenCache = new Map<string, { token: string; expiresAt: number }>();\n\nfunction getCacheKey(apiUrl: string, secret: string): string {\n // Create a unique cache key from apiUrl and secret\n // Using a separator that's unlikely to appear in URLs or secrets\n return `${apiUrl}::${secret}`;\n}\n\nexport async function getPublicToken(params: {\n apiUrl: string;\n secret: string;\n cacheTtlMs?: number;\n fetchImpl?: FetchImpl;\n}): Promise<string | null> {\n const { apiUrl, secret, cacheTtlMs = 3_600_000, fetchImpl = fetch } = params;\n\n const now = Date.now();\n const cacheKey = getCacheKey(apiUrl, secret);\n\n const cached = tokenCache.get(cacheKey);\n if (cached && cached.expiresAt > now) {\n return cached.token;\n }\n\n const token = await exchangeSecretForPublicToken(apiUrl, secret, fetchImpl);\n\n if (!token) {\n return null;\n }\n\n tokenCache.set(cacheKey, { token, expiresAt: now + cacheTtlMs });\n\n // Clean up expired entries to prevent memory leak\n for (const [key, value] of tokenCache.entries()) {\n if (value.expiresAt <= now) {\n tokenCache.delete(key);\n }\n }\n\n return token;\n}\n"],"mappings":";AAMA,eAAsB,6BACpB,QACA,QACA,YAAuB,OACC;CACxB,MAAM,MAAM,MAAM,UAAU,GAAG,OAAO,iBAAiB;EACrD,QAAQ;EACR,SAAS;GACP,eAAe,UAAU;GACzB,gBAAgB;GACjB;EACF,CAAC;AAEF,KAAI,CAAC,IAAI,GACP,QAAO;CAGT,MAAM,OAAQ,MAAM,IAAI,MAAM;AAC9B,KAAI,OAAO,KAAK,gBAAgB,YAAY,KAAK,YAAY,SAAS,EACpE,QAAO,KAAK;AAGd,QAAO;;AAIT,MAAM,6BAAa,IAAI,KAAmD;AAE1E,SAAS,YAAY,QAAgB,QAAwB;AAG3D,QAAO,GAAG,OAAO,IAAI;;AAGvB,eAAsB,eAAe,QAKV;CACzB,MAAM,EAAE,QAAQ,QAAQ,aAAa,MAAW,YAAY,UAAU;CAEtE,MAAM,MAAM,KAAK,KAAK;CACtB,MAAM,WAAW,YAAY,QAAQ,OAAO;CAE5C,MAAM,SAAS,WAAW,IAAI,SAAS;AACvC,KAAI,UAAU,OAAO,YAAY,IAC/B,QAAO,OAAO;CAGhB,MAAM,QAAQ,MAAM,6BAA6B,QAAQ,QAAQ,UAAU;AAE3E,KAAI,CAAC,MACH,QAAO;AAGT,YAAW,IAAI,UAAU;EAAE;EAAO,WAAW,MAAM;EAAY,CAAC;AAGhE,MAAK,MAAM,CAAC,KAAK,UAAU,WAAW,SAAS,CAC7C,KAAI,MAAM,aAAa,IACrB,YAAW,OAAO,IAAI;AAI1B,QAAO"}
@@ -0,0 +1,18 @@
1
+ import { Config } from "@interfere/types/sdk/config";
2
+ import { Env, Runtime } from "@interfere/types/sdk/runtime";
3
+ import { Envelope } from "@interfere/types/sdk/envelope";
4
+
5
+ //#region src/server/capture.d.ts
6
+ declare function toJsonBytes(obj: unknown): number[];
7
+ type ServerErrorMeta = Pick<Config["metadata"], "buildId" | "releaseId">;
8
+ type ServerErrorEnvelopeInput = ServerErrorMeta & {
9
+ error: unknown;
10
+ request?: Request;
11
+ context?: Record<string, unknown>;
12
+ environment: string | Env;
13
+ runtime?: string | Runtime;
14
+ };
15
+ declare function buildServerErrorEnvelope(input: ServerErrorEnvelopeInput): Envelope;
16
+ declare function sendEnvelopesToIngest(envelopes: Envelope[], ingestUrl: string, surfaceToken: string): Promise<void>;
17
+ //#endregion
18
+ export { ServerErrorEnvelopeInput, buildServerErrorEnvelope, sendEnvelopesToIngest, toJsonBytes };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.d.mts","names":[],"sources":["../../src/server/capture.ts"],"sourcesContent":[],"mappings":";;;;;iBAiBgB,WAAA;KA4EX,eAAA,GAAkB,KAAK;AA5EZ,KA8EJ,wBAAA,GAA2B,eA9EZ,GAAA;EA4EtB,KAAA,EAAA,OAAA;EAEO,OAAA,CAAA,EAEA,OAFA;EAA2B,OAAA,CAAA,EAG3B,MAH2B,CAAA,MAAA,EAAA,OAAA,CAAA;EAE3B,WAAA,EAAA,MAAA,GAEY,GAFZ;EACA,OAAA,CAAA,EAAA,MAAA,GAES,OAFT;CACY;AACH,iBAGL,wBAAA,CAHK,KAAA,EAIZ,wBAJY,CAAA,EAKlB,QALkB;AAAO,iBA2CN,qBAAA,CA3CM,SAAA,EA4Cf,QA5Ce,EAAA,EAAA,SAAA,EAAA,MAAA,EAAA,YAAA,EAAA,MAAA,CAAA,EA+CzB,OA/CyB,CAAA,IAAA,CAAA"}
@@ -0,0 +1,105 @@
1
+ import { withSpan } from "../effect/layers/tracer.layer.mjs";
2
+ import { Effect } from "effect";
3
+ import { v7 } from "uuid";
4
+ import { withInterfereLogger } from "@interfere/effect-utils/observability";
5
+ import { normalizeEnv, normalizeRuntime } from "@interfere/types/sdk/runtime";
6
+
7
+ //#region src/server/capture.ts
8
+ function toJsonBytes(obj) {
9
+ const encoder = new TextEncoder();
10
+ return Array.from(encoder.encode(JSON.stringify(obj)));
11
+ }
12
+ const X_INTERFERE_REQUEST_HEADER = "x-interfere-request";
13
+ /**
14
+ * Parse x-interfere-request header to extract session ID and request ID
15
+ * Format: {sessionId}/{requestId}
16
+ */
17
+ function parseInterfereRequestHeader(headerValue) {
18
+ if (!headerValue) return {
19
+ sessionId: null,
20
+ requestId: null
21
+ };
22
+ const parts = headerValue.split("/");
23
+ if (parts.length !== 2) return {
24
+ sessionId: null,
25
+ requestId: null
26
+ };
27
+ return {
28
+ sessionId: parts[0] || null,
29
+ requestId: parts[1] || null
30
+ };
31
+ }
32
+ /**
33
+ * Parse stack trace to extract frames
34
+ * Similar logic to client-side error parsing
35
+ */
36
+ const STACK_TRACE_REGEX = /at\s+(?:(.+?)\s+\()?(.+?):(\d+):(\d+)\)?/;
37
+ function parseStackTrace(stack) {
38
+ if (!stack) return [{
39
+ file: { reported: null },
40
+ line: { reported: null },
41
+ column: { reported: null },
42
+ fn: { reported: null }
43
+ }];
44
+ const lines = stack.split("\n");
45
+ const frames = [];
46
+ for (const line of lines) {
47
+ const match = line.match(STACK_TRACE_REGEX);
48
+ if (match) frames.push({
49
+ file: { reported: match[2] || null },
50
+ line: { reported: match[3] ? Number.parseInt(match[3], 10) : null },
51
+ column: { reported: match[4] ? Number.parseInt(match[4], 10) : null },
52
+ fn: { reported: match[1] || null }
53
+ });
54
+ }
55
+ return frames.length > 0 ? frames : [{
56
+ file: { reported: null },
57
+ line: { reported: null },
58
+ column: { reported: null },
59
+ fn: { reported: null }
60
+ }];
61
+ }
62
+ function buildServerErrorEnvelope(input) {
63
+ const { error, request, buildId, releaseId, environment, runtime } = input;
64
+ let sessionId;
65
+ if (request) sessionId = parseInterfereRequestHeader(request.headers.get(X_INTERFERE_REQUEST_HEADER)).sessionId ?? `server_${v7()}`;
66
+ else sessionId = `server_${v7()}`;
67
+ const errorObj = error;
68
+ const errorPayload = {
69
+ frames: parseStackTrace(errorObj?.stack),
70
+ message: errorObj?.message ?? String(error ?? "Unknown error"),
71
+ name: errorObj?.name ?? "Error",
72
+ stack: errorObj?.stack ?? null,
73
+ errorSource: "server"
74
+ };
75
+ return {
76
+ v: 0,
77
+ runtime: normalizeRuntime(runtime),
78
+ environment: normalizeEnv(environment),
79
+ clientTs: Date.now(),
80
+ sessionId,
81
+ type: "error",
82
+ payload: errorPayload,
83
+ buildId: buildId ?? "unknown",
84
+ releaseId: releaseId ?? "unknown",
85
+ uuid: v7()
86
+ };
87
+ }
88
+ async function sendEnvelopesToIngest(envelopes, ingestUrl, surfaceToken) {
89
+ const response = await Effect.runPromise(withInterfereLogger("react", withSpan("server.sendEnvelopes", Effect.promise(() => fetch(ingestUrl, {
90
+ method: "POST",
91
+ headers: {
92
+ "Content-Type": "application/json",
93
+ "x-interfere-surface": surfaceToken
94
+ },
95
+ body: JSON.stringify(envelopes),
96
+ keepalive: true
97
+ })))));
98
+ if (!response.ok) {
99
+ const errorText = await response.text().catch(() => "");
100
+ throw new Error(`Failed to send envelopes to ingest: ${response.status} ${response.statusText}${errorText ? ` - ${errorText}` : ""}`);
101
+ }
102
+ }
103
+
104
+ //#endregion
105
+ export { buildServerErrorEnvelope, sendEnvelopesToIngest, toJsonBytes };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.mjs","names":["frames: IngestedFrame[]","sessionId: string","uuidv7","errorPayload: ErrorEnvelopePayload"],"sources":["../../src/server/capture.ts"],"sourcesContent":["import { withInterfereLogger } from \"@interfere/effect-utils/observability\";\nimport type { IngestedFrame } from \"@interfere/types/data/frame\";\nimport type { Config } from \"@interfere/types/sdk/config\";\nimport type { Envelope } from \"@interfere/types/sdk/envelope\";\nimport type { ErrorEnvelopePayload } from \"@interfere/types/sdk/plugins/payload/errors\";\nimport {\n type Env,\n normalizeEnv,\n normalizeRuntime,\n type Runtime,\n} from \"@interfere/types/sdk/runtime\";\n\nimport { Effect } from \"effect\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nimport { withSpan } from \"../effect/layers/tracer.layer.js\";\n\nexport function toJsonBytes(obj: unknown): number[] {\n const encoder = new TextEncoder();\n return Array.from(encoder.encode(JSON.stringify(obj)));\n}\n\nconst X_INTERFERE_REQUEST_HEADER = \"x-interfere-request\";\n\n/**\n * Parse x-interfere-request header to extract session ID and request ID\n * Format: {sessionId}/{requestId}\n */\nfunction parseInterfereRequestHeader(headerValue: string | null): {\n sessionId: string | null;\n requestId: string | null;\n} {\n if (!headerValue) {\n return { sessionId: null, requestId: null };\n }\n\n const parts = headerValue.split(\"/\");\n if (parts.length !== 2) {\n return { sessionId: null, requestId: null };\n }\n\n return {\n sessionId: parts[0] || null,\n requestId: parts[1] || null,\n };\n}\n\n/**\n * Parse stack trace to extract frames\n * Similar logic to client-side error parsing\n */\nconst STACK_TRACE_REGEX = /at\\s+(?:(.+?)\\s+\\()?(.+?):(\\d+):(\\d+)\\)?/;\n\nfunction parseStackTrace(stack?: string): IngestedFrame[] {\n if (!stack) {\n return [\n {\n file: { reported: null },\n line: { reported: null },\n column: { reported: null },\n fn: { reported: null },\n },\n ];\n }\n\n const lines = stack.split(\"\\n\");\n const frames: IngestedFrame[] = [];\n\n for (const line of lines) {\n const match = line.match(STACK_TRACE_REGEX);\n\n if (match) {\n frames.push({\n file: { reported: match[2] || null },\n line: { reported: match[3] ? Number.parseInt(match[3], 10) : null },\n column: { reported: match[4] ? Number.parseInt(match[4], 10) : null },\n fn: { reported: match[1] || null },\n });\n }\n }\n\n return frames.length > 0\n ? frames\n : [\n {\n file: { reported: null },\n line: { reported: null },\n column: { reported: null },\n fn: { reported: null },\n },\n ];\n}\n\ntype ServerErrorMeta = Pick<Config[\"metadata\"], \"buildId\" | \"releaseId\">;\n\nexport type ServerErrorEnvelopeInput = ServerErrorMeta & {\n error: unknown;\n request?: Request;\n context?: Record<string, unknown>;\n environment: string | Env;\n runtime?: string | Runtime;\n};\n\nexport function buildServerErrorEnvelope(\n input: ServerErrorEnvelopeInput\n): Envelope {\n const { error, request, buildId, releaseId, environment, runtime } = input;\n\n // Extract session ID from x-interfere-request header\n let sessionId: string;\n if (request) {\n const headerValue = request.headers.get(X_INTERFERE_REQUEST_HEADER);\n const parsed = parseInterfereRequestHeader(headerValue);\n sessionId = parsed.sessionId ?? `server_${uuidv7()}`;\n } else {\n // Generate placeholder session ID if no request provided\n sessionId = `server_${uuidv7()}`;\n }\n\n // Build error payload matching ErrorEnvelopePayload schema\n const errorObj = error as Error;\n const errorPayload: ErrorEnvelopePayload = {\n frames: parseStackTrace(errorObj?.stack),\n message: errorObj?.message ?? String(error ?? \"Unknown error\"),\n name: errorObj?.name ?? \"Error\",\n stack: errorObj?.stack ?? null,\n errorSource: \"server\",\n };\n\n return {\n v: 0,\n runtime: normalizeRuntime(runtime),\n environment: normalizeEnv(environment),\n clientTs: Date.now(),\n sessionId,\n type: \"error\",\n payload: errorPayload,\n buildId: buildId ?? \"unknown\",\n releaseId: releaseId ?? \"unknown\",\n uuid: uuidv7(),\n };\n}\n\nexport async function sendEnvelopesToIngest(\n envelopes: Envelope[],\n ingestUrl: string,\n surfaceToken: string\n): Promise<void> {\n const response = await Effect.runPromise(\n withInterfereLogger(\n \"react\",\n withSpan(\n \"server.sendEnvelopes\",\n Effect.promise(() =>\n fetch(ingestUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-interfere-surface\": surfaceToken,\n },\n body: JSON.stringify(envelopes),\n keepalive: true,\n })\n )\n )\n )\n );\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"\");\n throw new Error(\n `Failed to send envelopes to ingest: ${response.status} ${response.statusText}${\n errorText ? ` - ${errorText}` : \"\"\n }`\n );\n }\n}\n"],"mappings":";;;;;;;AAiBA,SAAgB,YAAY,KAAwB;CAClD,MAAM,UAAU,IAAI,aAAa;AACjC,QAAO,MAAM,KAAK,QAAQ,OAAO,KAAK,UAAU,IAAI,CAAC,CAAC;;AAGxD,MAAM,6BAA6B;;;;;AAMnC,SAAS,4BAA4B,aAGnC;AACA,KAAI,CAAC,YACH,QAAO;EAAE,WAAW;EAAM,WAAW;EAAM;CAG7C,MAAM,QAAQ,YAAY,MAAM,IAAI;AACpC,KAAI,MAAM,WAAW,EACnB,QAAO;EAAE,WAAW;EAAM,WAAW;EAAM;AAG7C,QAAO;EACL,WAAW,MAAM,MAAM;EACvB,WAAW,MAAM,MAAM;EACxB;;;;;;AAOH,MAAM,oBAAoB;AAE1B,SAAS,gBAAgB,OAAiC;AACxD,KAAI,CAAC,MACH,QAAO,CACL;EACE,MAAM,EAAE,UAAU,MAAM;EACxB,MAAM,EAAE,UAAU,MAAM;EACxB,QAAQ,EAAE,UAAU,MAAM;EAC1B,IAAI,EAAE,UAAU,MAAM;EACvB,CACF;CAGH,MAAM,QAAQ,MAAM,MAAM,KAAK;CAC/B,MAAMA,SAA0B,EAAE;AAElC,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,QAAQ,KAAK,MAAM,kBAAkB;AAE3C,MAAI,MACF,QAAO,KAAK;GACV,MAAM,EAAE,UAAU,MAAM,MAAM,MAAM;GACpC,MAAM,EAAE,UAAU,MAAM,KAAK,OAAO,SAAS,MAAM,IAAI,GAAG,GAAG,MAAM;GACnE,QAAQ,EAAE,UAAU,MAAM,KAAK,OAAO,SAAS,MAAM,IAAI,GAAG,GAAG,MAAM;GACrE,IAAI,EAAE,UAAU,MAAM,MAAM,MAAM;GACnC,CAAC;;AAIN,QAAO,OAAO,SAAS,IACnB,SACA,CACE;EACE,MAAM,EAAE,UAAU,MAAM;EACxB,MAAM,EAAE,UAAU,MAAM;EACxB,QAAQ,EAAE,UAAU,MAAM;EAC1B,IAAI,EAAE,UAAU,MAAM;EACvB,CACF;;AAaP,SAAgB,yBACd,OACU;CACV,MAAM,EAAE,OAAO,SAAS,SAAS,WAAW,aAAa,YAAY;CAGrE,IAAIC;AACJ,KAAI,QAGF,aADe,4BADK,QAAQ,QAAQ,IAAI,2BAA2B,CACZ,CACpC,aAAa,UAAUC,IAAQ;KAGlD,aAAY,UAAUA,IAAQ;CAIhC,MAAM,WAAW;CACjB,MAAMC,eAAqC;EACzC,QAAQ,gBAAgB,UAAU,MAAM;EACxC,SAAS,UAAU,WAAW,OAAO,SAAS,gBAAgB;EAC9D,MAAM,UAAU,QAAQ;EACxB,OAAO,UAAU,SAAS;EAC1B,aAAa;EACd;AAED,QAAO;EACL,GAAG;EACH,SAAS,iBAAiB,QAAQ;EAClC,aAAa,aAAa,YAAY;EACtC,UAAU,KAAK,KAAK;EACpB;EACA,MAAM;EACN,SAAS;EACT,SAAS,WAAW;EACpB,WAAW,aAAa;EACxB,MAAMD,IAAQ;EACf;;AAGH,eAAsB,sBACpB,WACA,WACA,cACe;CACf,MAAM,WAAW,MAAM,OAAO,WAC5B,oBACE,SACA,SACE,wBACA,OAAO,cACL,MAAM,WAAW;EACf,QAAQ;EACR,SAAS;GACP,gBAAgB;GAChB,uBAAuB;GACxB;EACD,MAAM,KAAK,UAAU,UAAU;EAC/B,WAAW;EACZ,CAAC,CACH,CACF,CACF,CACF;AAED,KAAI,CAAC,SAAS,IAAI;EAChB,MAAM,YAAY,MAAM,SAAS,MAAM,CAAC,YAAY,GAAG;AACvD,QAAM,IAAI,MACR,uCAAuC,SAAS,OAAO,GAAG,SAAS,aACjE,YAAY,MAAM,cAAc,KAEnC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interfere/react",
3
- "version": "0.0.1",
3
+ "version": "0.0.2-alpha.1",
4
4
  "license": "MIT",
5
5
  "description": "Build apps that never break.",
6
6
  "keywords": [
@@ -20,54 +20,87 @@
20
20
  "dist"
21
21
  ],
22
22
  "type": "module",
23
- "main": "./dist/index.js",
24
- "types": "./dist/index.d.ts",
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
+ },
25
35
  "exports": {
26
- ".": {
27
- "types": "./dist/index.d.ts",
28
- "default": "./dist/index.js"
36
+ "./provider": {
37
+ "@source": "./src/provider.tsx",
38
+ "types": "./dist/provider.d.mts",
39
+ "default": "./dist/provider.mjs"
29
40
  },
30
- "./client": {
31
- "types": "./dist/client.d.ts",
32
- "default": "./dist/client.js"
41
+ "./server/*": {
42
+ "@source": "./src/server/*.ts",
43
+ "types": "./dist/server/*.d.mts",
44
+ "default": "./dist/server/*.mjs"
33
45
  },
34
- "./provider": {
35
- "types": "./dist/provider.d.ts",
36
- "default": "./dist/provider.js"
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
+ "./*": {
57
+ "@source": "./src/*.ts",
58
+ "types": "./dist/*.d.mts",
59
+ "default": "./dist/*.mjs"
37
60
  }
38
61
  },
62
+ "sideEffects": false,
39
63
  "publishConfig": {
40
64
  "access": "public"
41
65
  },
42
66
  "dependencies": {
67
+ "@effect/platform": "^0.94.0",
43
68
  "@rrweb/packer": "2.0.0-alpha.18",
44
- "@rrweb/types": "2.0.0-alpha.18",
69
+ "@ua-parser-js/pro-enterprise": "^2.0.6",
70
+ "effect": "^3.19.13",
45
71
  "nanoid": "^5.1.6",
46
72
  "rrweb": "2.0.0-alpha.18",
47
73
  "uuid": "^13.0.0",
48
- "@interfere/constants": "0.0.1",
49
- "@interfere/schemas": "0.0.7"
74
+ "zod": "^4.2.1",
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"
50
78
  },
51
79
  "peerDependencies": {
52
80
  "react": ">=18",
53
81
  "react-dom": ">=18"
54
82
  },
55
83
  "devDependencies": {
56
- "@types/node": "22.15.29",
57
- "@types/react": "19.1.16",
58
- "@types/react-dom": "19.1.9",
59
- "@vitest/coverage-v8": "^3.2.4",
60
- "jsdom": "^27.0.0",
61
- "react": "^19.1.1",
62
- "react-dom": "^19.1.1",
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.3",
63
94
  "typescript": "5.9.3",
64
- "vitest": "^3.2.4",
65
- "@interfere/typescript-config": "1.0.2"
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"
66
99
  },
67
100
  "scripts": {
68
- "build": "tsc",
69
- "dev": "tsc --watch",
70
- "check-types": "tsc --noEmit --incremental",
101
+ "build": "tsdown",
102
+ "dev": "tsdown --watch",
103
+ "typecheck": "tsc --noEmit --incremental",
71
104
  "test": "vitest run --coverage"
72
105
  }
73
106
  }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=client.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/client.test.ts"],"names":[],"mappings":""}