@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,48 @@
1
+ import package_default from "../../package.mjs";
2
+ import { Effect } from "effect";
3
+ import { UAParser } from "@ua-parser-js/pro-enterprise";
4
+
5
+ //#region src/core/runtime/context.ts
6
+ function getContextProperties() {
7
+ return Effect.gen(function* () {
8
+ if (typeof window === "undefined") throw new Error("getContextProperties can only be called in the browser environment");
9
+ const userAgent = window.navigator.userAgent;
10
+ const parser = UAParser(userAgent);
11
+ const result = yield* Effect.sync(() => parser.withClientHints());
12
+ const browser = yield* Effect.sync(() => {
13
+ if (!result.browser) return null;
14
+ return result.browser.withFeatureCheck();
15
+ });
16
+ return {
17
+ ...result,
18
+ ...browser ? { browser } : {},
19
+ ...getScreenProperties(),
20
+ ...getCaptureSourceProperties()
21
+ };
22
+ });
23
+ }
24
+ function getScreenProperties() {
25
+ if (typeof window === "undefined") throw new Error("getScreenProperties can only be called in the browser environment");
26
+ return {
27
+ viewport: {
28
+ viewport_width: window.innerWidth,
29
+ viewport_height: window.innerHeight
30
+ },
31
+ screen: {
32
+ screen_height: window.screen.height,
33
+ screen_width: window.screen.width
34
+ }
35
+ };
36
+ }
37
+ function getCaptureSourceProperties() {
38
+ if (typeof window === "undefined") throw new Error("getCaptureSourceProperties can only be called in the browser environment");
39
+ const { name, version } = package_default;
40
+ return { sdk: {
41
+ name,
42
+ version,
43
+ language: "javascript"
44
+ } };
45
+ }
46
+
47
+ //#endregion
48
+ export { getContextProperties };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.mjs","names":["packageJson"],"sources":["../../../src/core/runtime/context.ts"],"sourcesContent":["import { type IResult, UAParser } from \"@ua-parser-js/pro-enterprise\";\nimport { Effect } from \"effect\";\n\nimport packageJson from \"../../../package.json\" with { type: \"json\" };\n\ninterface ScreenProperties {\n viewport: {\n viewport_width: number;\n viewport_height: number;\n };\n screen: {\n screen_height: number;\n screen_width: number;\n };\n}\n\ninterface CaptureSourceProperties {\n sdk: {\n name: string;\n version: string;\n language: string;\n };\n}\n\nexport type ContextProperties = ScreenProperties &\n CaptureSourceProperties &\n IResult &\n Record<string, unknown>;\n\nexport function getContextProperties(): Effect.Effect<ContextProperties> {\n return Effect.gen(function* () {\n if (typeof window === \"undefined\") {\n throw new Error(\n \"getContextProperties can only be called in the browser environment\"\n );\n }\n\n const userAgent = window.navigator.userAgent;\n const parser = UAParser(userAgent);\n\n const result = (yield* Effect.sync(() =>\n parser.withClientHints()\n )) as IResult;\n\n const browser = (yield* Effect.sync(() => {\n if (!result.browser) {\n return null;\n }\n return result.browser.withFeatureCheck();\n })) as IResult[\"browser\"] | null;\n\n return {\n ...result,\n ...(browser ? { browser } : {}),\n ...getScreenProperties(),\n ...getCaptureSourceProperties(),\n } satisfies ContextProperties;\n });\n}\n\nfunction getScreenProperties(): ScreenProperties {\n if (typeof window === \"undefined\") {\n throw new Error(\n \"getScreenProperties can only be called in the browser environment\"\n );\n }\n\n return {\n viewport: {\n viewport_width: window.innerWidth,\n viewport_height: window.innerHeight,\n },\n screen: {\n screen_height: window.screen.height,\n screen_width: window.screen.width,\n },\n };\n}\n\nfunction getCaptureSourceProperties(): CaptureSourceProperties {\n if (typeof window === \"undefined\") {\n throw new Error(\n \"getCaptureSourceProperties can only be called in the browser environment\"\n );\n }\n\n const { name, version } = packageJson;\n\n return {\n sdk: {\n name,\n version,\n language: \"javascript\",\n },\n };\n}\n"],"mappings":";;;;;AA6BA,SAAgB,uBAAyD;AACvE,QAAO,OAAO,IAAI,aAAa;AAC7B,MAAI,OAAO,WAAW,YACpB,OAAM,IAAI,MACR,qEACD;EAGH,MAAM,YAAY,OAAO,UAAU;EACnC,MAAM,SAAS,SAAS,UAAU;EAElC,MAAM,SAAU,OAAO,OAAO,WAC5B,OAAO,iBAAiB,CACzB;EAED,MAAM,UAAW,OAAO,OAAO,WAAW;AACxC,OAAI,CAAC,OAAO,QACV,QAAO;AAET,UAAO,OAAO,QAAQ,kBAAkB;IACxC;AAEF,SAAO;GACL,GAAG;GACH,GAAI,UAAU,EAAE,SAAS,GAAG,EAAE;GAC9B,GAAG,qBAAqB;GACxB,GAAG,4BAA4B;GAChC;GACD;;AAGJ,SAAS,sBAAwC;AAC/C,KAAI,OAAO,WAAW,YACpB,OAAM,IAAI,MACR,oEACD;AAGH,QAAO;EACL,UAAU;GACR,gBAAgB,OAAO;GACvB,iBAAiB,OAAO;GACzB;EACD,QAAQ;GACN,eAAe,OAAO,OAAO;GAC7B,cAAc,OAAO,OAAO;GAC7B;EACF;;AAGH,SAAS,6BAAsD;AAC7D,KAAI,OAAO,WAAW,YACpB,OAAM,IAAI,MACR,2EACD;CAGH,MAAM,EAAE,MAAM,YAAYA;AAE1B,QAAO,EACL,KAAK;EACH;EACA;EACA,UAAU;EACX,EACF"}
@@ -0,0 +1,10 @@
1
+ import { Config } from "@interfere/types/sdk/config";
2
+
3
+ //#region src/core/runtime/ingest-target.d.ts
4
+ interface IngestTarget {
5
+ url: string;
6
+ headers: Headers;
7
+ }
8
+ declare function deriveIngestTarget(config: Config): IngestTarget;
9
+ //#endregion
10
+ export { IngestTarget, deriveIngestTarget };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingest-target.d.mts","names":[],"sources":["../../../src/core/runtime/ingest-target.ts"],"sourcesContent":[],"mappings":";;;UAEiB,YAAA;;EAAA,OAAA,EAEN,OAFkB;AAK7B;iBAAgB,kBAAA,SAA2B,SAAS"}
@@ -0,0 +1,15 @@
1
+ //#region src/core/runtime/ingest-target.ts
2
+ function deriveIngestTarget(config) {
3
+ if ("proxyUrl" in config) return {
4
+ url: config.proxyUrl,
5
+ headers: new Headers([["Content-Type", "application/json"]])
6
+ };
7
+ if ("ingestUrl" in config && "surfaceToken" in config) return {
8
+ url: config.ingestUrl,
9
+ headers: new Headers([["Content-Type", "application/json"], ["x-interfere-surface", config.surfaceToken]])
10
+ };
11
+ throw new Error("Invalid SDK config: must provide proxyUrl or (ingestUrl + surfaceToken)");
12
+ }
13
+
14
+ //#endregion
15
+ export { deriveIngestTarget };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ingest-target.mjs","names":[],"sources":["../../../src/core/runtime/ingest-target.ts"],"sourcesContent":["import type { Config } from \"@interfere/types/sdk/config\";\n\nexport interface IngestTarget {\n url: string;\n headers: Headers;\n}\n\nexport function deriveIngestTarget(config: Config): IngestTarget {\n if (\"proxyUrl\" in config) {\n return {\n url: config.proxyUrl,\n headers: new Headers([[\"Content-Type\", \"application/json\"]]),\n };\n }\n\n if (\"ingestUrl\" in config && \"surfaceToken\" in config) {\n return {\n url: config.ingestUrl,\n headers: new Headers([\n [\"Content-Type\", \"application/json\"],\n [\"x-interfere-surface\", config.surfaceToken],\n ]),\n };\n }\n\n throw new Error(\n \"Invalid SDK config: must provide proxyUrl or (ingestUrl + surfaceToken)\"\n );\n}\n"],"mappings":";AAOA,SAAgB,mBAAmB,QAA8B;AAC/D,KAAI,cAAc,OAChB,QAAO;EACL,KAAK,OAAO;EACZ,SAAS,IAAI,QAAQ,CAAC,CAAC,gBAAgB,mBAAmB,CAAC,CAAC;EAC7D;AAGH,KAAI,eAAe,UAAU,kBAAkB,OAC7C,QAAO;EACL,KAAK,OAAO;EACZ,SAAS,IAAI,QAAQ,CACnB,CAAC,gBAAgB,mBAAmB,EACpC,CAAC,uBAAuB,OAAO,aAAa,CAC7C,CAAC;EACH;AAGH,OAAM,IAAI,MACR,0EACD"}
@@ -0,0 +1,85 @@
1
+ import { SessionServiceTag } from "../effect/layers/session.layer.mjs";
2
+ import { ConfigTag } from "../effect/tags.mjs";
3
+ import { AnyEventDefinition } from "./events/plugin-event-types.mjs";
4
+ import { EventPayload } from "./events/event-registry.mjs";
5
+ import { ContextServiceTag } from "../effect/layers/context.layer.mjs";
6
+ import { HttpServiceTag } from "../effect/layers/http.layer.mjs";
7
+ import { QueueServiceTag } from "../effect/layers/queue.layer.mjs";
8
+ import { capture, captureEffect } from "../client.mjs";
9
+ import { ErrorsAPI } from "./plugins/impl/errors.mjs";
10
+ import { ReplayAPI } from "./plugins/impl/replay.mjs";
11
+ import { ServerTracingAPI } from "./plugins/impl/server-tracing.mjs";
12
+ import { Effect } from "effect";
13
+ import { Config } from "@interfere/types/sdk/config";
14
+ import { EventType } from "@interfere/types/sdk/plugins/lib/types";
15
+ import { Envelope } from "@interfere/types/sdk/envelope";
16
+ import { logDebug, logError, logFatal, logInfo, logTrace, logWarning } from "effect/Effect";
17
+
18
+ //#region src/core/schemas.d.ts
19
+ interface PluginLogger {
20
+ /**
21
+ * @see {@link logTrace}
22
+ */
23
+ trace: (...message: Parameters<typeof logTrace>) => void;
24
+ /**
25
+ * @see {@link logDebug}
26
+ */
27
+ debug: (...message: Parameters<typeof logDebug>) => void;
28
+ /**
29
+ * @see {@link logInfo}
30
+ */
31
+ info: (...message: Parameters<typeof logInfo>) => void;
32
+ /**
33
+ * @see {@link logWarning}
34
+ */
35
+ warn: (...message: Parameters<typeof logWarning>) => void;
36
+ /**
37
+ * @see {@link logError}
38
+ */
39
+ error: (...message: Parameters<typeof logError>) => void;
40
+ /**
41
+ * @see {@link logFatal}
42
+ */
43
+ fatal: (...message: Parameters<typeof logFatal>) => void;
44
+ }
45
+ interface PluginContext {
46
+ capture: typeof captureEffect;
47
+ config: Config;
48
+ run: <A, E>(eff: Effect.Effect<A, E, ContextServiceTag | ConfigTag | HttpServiceTag | SessionServiceTag | QueueServiceTag>) => void;
49
+ span: <A, E>(label: string, eff: Effect.Effect<A, E, ContextServiceTag | ConfigTag | HttpServiceTag | SessionServiceTag | QueueServiceTag>) => void;
50
+ captureNow: <T extends EventType>(type: T, payload: EventPayload<T>) => void;
51
+ log: PluginLogger;
52
+ }
53
+ interface ProviderContext {
54
+ capture: typeof capture;
55
+ }
56
+ type OptionalPluginApis = Partial<PluginApiMap>;
57
+ type InterfereProviderValue = ProviderContext & OptionalPluginApis;
58
+ interface KnownPluginApis {
59
+ errors: ErrorsAPI;
60
+ replay: ReplayAPI;
61
+ rageClick: null;
62
+ aiSummary: null;
63
+ pageEvents: null;
64
+ serverTracing: ServerTracingAPI;
65
+ }
66
+ type PluginApiMap = KnownPluginApis & Record<string, unknown>;
67
+ interface PluginExpose<K$1 extends string, A> {
68
+ key: K$1;
69
+ api?: A;
70
+ cleanup?: () => void;
71
+ }
72
+ type PluginReturn<K$1 extends string, A> = undefined | (() => void) | PluginExpose<K$1, A> | Promise<PluginExpose<K$1, A> | (() => void) | undefined>;
73
+ type PluginSetupFn<K$1 extends string, A> = (ctx: PluginContext) => PluginReturn<K$1, A>;
74
+ interface Plugin<K$1 extends string = string, A = unknown> {
75
+ name: string;
76
+ events?: readonly AnyEventDefinition[];
77
+ setup: PluginSetupFn<K$1, A>;
78
+ }
79
+ type PluginsUnion<P> = P extends readonly (infer U)[] ? U : never;
80
+ type PluginKeyOf<U> = U extends Plugin<infer K, unknown> ? K : never;
81
+ type ApiOf<U, K$1 extends string> = Extract<U, Plugin<K$1, unknown>> extends Plugin<K$1, infer A> ? A : never;
82
+ type InferredApis<P extends readonly Plugin<string, unknown>[]> = { [K in PluginKeyOf<PluginsUnion<P>>]: ApiOf<PluginsUnion<P>, Extract<K, string>> };
83
+ type Sender = (envelopes: Envelope[]) => Promise<void>;
84
+ //#endregion
85
+ export { InferredApis, InterfereProviderValue, KnownPluginApis, Plugin, PluginApiMap, PluginContext, PluginExpose, PluginReturn, PluginSetupFn, Sender };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.mts","names":[],"sources":["../../src/core/schemas.ts"],"sourcesContent":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,9 @@
1
+ import { SessionServiceTag } from "./layers/session.layer.mjs";
2
+ import { ConfigTag } from "./tags.mjs";
3
+ import { Effect } from "effect";
4
+ import { Envelope } from "@interfere/types/sdk/envelope";
5
+
6
+ //#region src/effect/build-envelope.d.ts
7
+ declare function buildEnvelopeEffect<T extends Envelope>(values: Pick<T, "type" | "payload">): Effect.Effect<Envelope, never, SessionServiceTag | ConfigTag>;
8
+ //#endregion
9
+ export { buildEnvelopeEffect };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-envelope.d.mts","names":[],"sources":["../../src/effect/build-envelope.ts"],"sourcesContent":[],"mappings":";;;;;;iBASgB,8BAA8B,kBACpC,KAAK,yBACZ,MAAA,CAAO,OAAO,iBAAiB,oBAAoB"}
@@ -0,0 +1,29 @@
1
+ import { getRuntime } from "../core/runtime/config.mjs";
2
+ import { SessionServiceTag } from "./layers/session.layer.mjs";
3
+ import { ConfigTag } from "./tags.mjs";
4
+ import { Effect } from "effect";
5
+ import { v7 } from "uuid";
6
+
7
+ //#region src/effect/build-envelope.ts
8
+ function buildEnvelopeEffect(values) {
9
+ return Effect.gen(function* () {
10
+ const cfg = yield* ConfigTag;
11
+ const session = yield* SessionServiceTag;
12
+ yield* session.ensureWindowId();
13
+ yield* session.updateActivity();
14
+ const sessionIdOpt = yield* session.getSessionId();
15
+ const session_id = sessionIdOpt._tag === "Some" ? sessionIdOpt.value : null;
16
+ return {
17
+ v: 0,
18
+ ...cfg.metadata,
19
+ runtime: getRuntime(),
20
+ clientTs: Date.now(),
21
+ sessionId: session_id,
22
+ uuid: v7(),
23
+ ...values
24
+ };
25
+ });
26
+ }
27
+
28
+ //#endregion
29
+ export { buildEnvelopeEffect };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-envelope.mjs","names":["uuidv7"],"sources":["../../src/effect/build-envelope.ts"],"sourcesContent":["import type { Envelope } from \"@interfere/types/sdk/envelope\";\n\nimport { Effect } from \"effect\";\nimport { v7 as uuidv7 } from \"uuid\";\n\nimport { getRuntime } from \"../core/runtime/config.js\";\nimport { SessionServiceTag } from \"./layers/session.layer.js\";\nimport { ConfigTag } from \"./tags.js\";\n\nexport function buildEnvelopeEffect<T extends Envelope>(\n values: Pick<T, \"type\" | \"payload\">\n): Effect.Effect<Envelope, never, SessionServiceTag | ConfigTag> {\n return Effect.gen(function* () {\n const cfg = yield* ConfigTag;\n const session = yield* SessionServiceTag;\n\n // Side-effectful session/window tracking\n yield* session.ensureWindowId();\n yield* session.updateActivity();\n\n // Resolve session id (may be none)\n const sessionIdOpt = yield* session.getSessionId();\n const session_id = sessionIdOpt._tag === \"Some\" ? sessionIdOpt.value : null;\n\n const envelope = {\n v: 0 as const,\n ...cfg.metadata,\n runtime: getRuntime(),\n clientTs: Date.now(),\n sessionId: session_id,\n uuid: uuidv7(),\n ...values,\n } as Envelope;\n\n return envelope;\n });\n}\n"],"mappings":";;;;;;;AASA,SAAgB,oBACd,QAC+D;AAC/D,QAAO,OAAO,IAAI,aAAa;EAC7B,MAAM,MAAM,OAAO;EACnB,MAAM,UAAU,OAAO;AAGvB,SAAO,QAAQ,gBAAgB;AAC/B,SAAO,QAAQ,gBAAgB;EAG/B,MAAM,eAAe,OAAO,QAAQ,cAAc;EAClD,MAAM,aAAa,aAAa,SAAS,SAAS,aAAa,QAAQ;AAYvE,SAViB;GACf,GAAG;GACH,GAAG,IAAI;GACP,SAAS,YAAY;GACrB,UAAU,KAAK,KAAK;GACpB,WAAW;GACX,MAAMA,IAAQ;GACd,GAAG;GACJ;GAGD"}
@@ -0,0 +1,36 @@
1
+ import * as effect_Types0 from "effect/Types";
2
+ import * as effect_Cause0 from "effect/Cause";
3
+
4
+ //#region src/effect/errors.d.ts
5
+ declare const HttpError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
6
+ readonly _tag: "HttpError";
7
+ } & Readonly<A>;
8
+ declare class HttpError extends HttpError_base<{
9
+ readonly status: number;
10
+ readonly message: string;
11
+ readonly url?: string;
12
+ readonly body?: string;
13
+ }> {}
14
+ declare const ValidationError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
15
+ readonly _tag: "ValidationError";
16
+ } & Readonly<A>;
17
+ declare class ValidationError extends ValidationError_base<{
18
+ readonly message: string;
19
+ readonly payload: unknown;
20
+ readonly issues?: unknown;
21
+ }> {}
22
+ declare const ConfigError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
23
+ readonly _tag: "ConfigError";
24
+ } & Readonly<A>;
25
+ declare class ConfigError extends ConfigError_base<{
26
+ readonly message: string;
27
+ }> {}
28
+ declare const StorageError_base: new <A extends Record<string, any> = {}>(args: effect_Types0.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P] }) => effect_Cause0.YieldableError & {
29
+ readonly _tag: "StorageError";
30
+ } & Readonly<A>;
31
+ declare class StorageError extends StorageError_base<{
32
+ readonly message: string;
33
+ readonly operation: "load" | "save" | "append" | "remove" | "drop";
34
+ }> {}
35
+ //#endregion
36
+ export { ConfigError, HttpError, StorageError, ValidationError };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.mts","names":[],"sources":["../../src/effect/errors.ts"],"sourcesContent":[],"mappings":";;;;;;;cAEa,SAAA,SAAkB;;;;;;cAK1B;;;cAEQ,eAAA,SAAwB;;;;AAPrC,CAAA,CAAA,CAAA;cAWK;;;cAEQ,WAAA,SAAoB;;;cAE5B;;;cAEQ,YAAA,SAAqB;;EAVrB,SAAA,SAAgB,EAAA,MAAA,GAAA,MAAQ,GAAA,QAAA,GAAA,QAAA,GAAA,MAAA;AAIhC,CAAA,CAAA,CAAA"}
@@ -0,0 +1,10 @@
1
+ import { Data } from "effect";
2
+
3
+ //#region src/effect/errors.ts
4
+ var HttpError = class extends Data.TaggedError("HttpError") {};
5
+ var ValidationError = class extends Data.TaggedError("ValidationError") {};
6
+ var ConfigError = class extends Data.TaggedError("ConfigError") {};
7
+ var StorageError = class extends Data.TaggedError("StorageError") {};
8
+
9
+ //#endregion
10
+ export { ConfigError, HttpError, StorageError, ValidationError };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.mjs","names":[],"sources":["../../src/effect/errors.ts"],"sourcesContent":["import { Data } from \"effect\";\n\nexport class HttpError extends Data.TaggedError(\"HttpError\")<{\n readonly status: number;\n readonly message: string;\n readonly url?: string;\n readonly body?: string;\n}> {}\n\nexport class ValidationError extends Data.TaggedError(\"ValidationError\")<{\n readonly message: string;\n readonly payload: unknown;\n readonly issues?: unknown;\n}> {}\n\nexport class ConfigError extends Data.TaggedError(\"ConfigError\")<{\n readonly message: string;\n}> {}\n\nexport class StorageError extends Data.TaggedError(\"StorageError\")<{\n readonly message: string;\n readonly operation: \"load\" | \"save\" | \"append\" | \"remove\" | \"drop\";\n}> {}\n"],"mappings":";;;AAEA,IAAa,YAAb,cAA+B,KAAK,YAAY,YAAY,CAKzD;AAEH,IAAa,kBAAb,cAAqC,KAAK,YAAY,kBAAkB,CAIrE;AAEH,IAAa,cAAb,cAAiC,KAAK,YAAY,cAAc,CAE7D;AAEH,IAAa,eAAb,cAAkC,KAAK,YAAY,eAAe,CAG/D"}
@@ -0,0 +1,13 @@
1
+ import { Config } from "@interfere/types/sdk/config";
2
+ import { Runtime } from "@interfere/types/sdk/runtime";
3
+
4
+ //#region src/effect/layers/config.layer.d.ts
5
+ type SdkConfig = Config & {
6
+ runtime: Runtime;
7
+ };
8
+ interface ConfigService {
9
+ get: () => SdkConfig;
10
+ }
11
+ declare function createConfigService(input: unknown): ConfigService;
12
+ //#endregion
13
+ export { ConfigService, SdkConfig, createConfigService };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.layer.d.mts","names":[],"sources":["../../../src/effect/layers/config.layer.ts"],"sourcesContent":[],"mappings":";;;;KAMY,SAAA,GAAY;WAAoB;AAA5C,CAAA;AAEiB,UAAA,aAAA,CAAa;EASd,GAAA,EAAA,GAAA,GARH,SAQG;;iBAAA,mBAAA,kBAAqC"}
@@ -0,0 +1,21 @@
1
+ import { getRuntime } from "../../core/runtime/config.mjs";
2
+ import { configSchema } from "@interfere/types/sdk/config";
3
+
4
+ //#region src/effect/layers/config.layer.ts
5
+ const MAX_BATCH_SIZE = 1e3;
6
+ const MIN_BATCH_SIZE = 1;
7
+ const MAX_BATCH_MS = 6e4;
8
+ const MIN_BATCH_MS = 100;
9
+ function createConfigService(input) {
10
+ const parsed = configSchema.parse(input);
11
+ if (parsed.batch.size < MIN_BATCH_SIZE || parsed.batch.size > MAX_BATCH_SIZE) throw new Error(`Invalid batch.size: ${parsed.batch.size}. Must be between ${MIN_BATCH_SIZE} and ${MAX_BATCH_SIZE}`);
12
+ if (parsed.batch.ms < MIN_BATCH_MS || parsed.batch.ms > MAX_BATCH_MS) throw new Error(`Invalid batch.ms: ${parsed.batch.ms}. Must be between ${MIN_BATCH_MS}ms and ${MAX_BATCH_MS}ms`);
13
+ const current = {
14
+ ...parsed,
15
+ runtime: getRuntime()
16
+ };
17
+ return { get: () => current };
18
+ }
19
+
20
+ //#endregion
21
+ export { createConfigService };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.layer.mjs","names":[],"sources":["../../../src/effect/layers/config.layer.ts"],"sourcesContent":["import type { Config } from \"@interfere/types/sdk/config\";\nimport { configSchema } from \"@interfere/types/sdk/config\";\nimport type { Runtime } from \"@interfere/types/sdk/runtime\";\n\nimport { getRuntime } from \"../../core/runtime/config.js\";\n\nexport type SdkConfig = Config & { runtime: Runtime };\n\nexport interface ConfigService {\n get: () => SdkConfig;\n}\n\nconst MAX_BATCH_SIZE = 1000;\nconst MIN_BATCH_SIZE = 1;\nconst MAX_BATCH_MS = 60_000;\nconst MIN_BATCH_MS = 100;\n\nexport function createConfigService(input: unknown): ConfigService {\n const parsed = configSchema.parse(input) as Required<Config>;\n\n // Validate batch configuration\n if (\n parsed.batch.size < MIN_BATCH_SIZE ||\n parsed.batch.size > MAX_BATCH_SIZE\n ) {\n throw new Error(\n `Invalid batch.size: ${parsed.batch.size}. Must be between ${MIN_BATCH_SIZE} and ${MAX_BATCH_SIZE}`\n );\n }\n\n if (parsed.batch.ms < MIN_BATCH_MS || parsed.batch.ms > MAX_BATCH_MS) {\n throw new Error(\n `Invalid batch.ms: ${parsed.batch.ms}. Must be between ${MIN_BATCH_MS}ms and ${MAX_BATCH_MS}ms`\n );\n }\n\n const current = { ...parsed, runtime: getRuntime() } as Config & {\n runtime: Runtime;\n };\n return {\n get: () => current,\n };\n}\n"],"mappings":";;;;AAYA,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AACvB,MAAM,eAAe;AACrB,MAAM,eAAe;AAErB,SAAgB,oBAAoB,OAA+B;CACjE,MAAM,SAAS,aAAa,MAAM,MAAM;AAGxC,KACE,OAAO,MAAM,OAAO,kBACpB,OAAO,MAAM,OAAO,eAEpB,OAAM,IAAI,MACR,uBAAuB,OAAO,MAAM,KAAK,oBAAoB,eAAe,OAAO,iBACpF;AAGH,KAAI,OAAO,MAAM,KAAK,gBAAgB,OAAO,MAAM,KAAK,aACtD,OAAM,IAAI,MACR,qBAAqB,OAAO,MAAM,GAAG,oBAAoB,aAAa,SAAS,aAAa,IAC7F;CAGH,MAAM,UAAU;EAAE,GAAG;EAAQ,SAAS,YAAY;EAAE;AAGpD,QAAO,EACL,WAAW,SACZ"}
@@ -0,0 +1,12 @@
1
+ import { ContextProperties } from "../../core/runtime/context.mjs";
2
+ import { Context, Effect, Layer } from "effect";
3
+
4
+ //#region src/effect/layers/context.layer.d.ts
5
+ interface ContextService {
6
+ readonly getOnce: () => Effect.Effect<ContextProperties>;
7
+ }
8
+ declare const ContextServiceTag_base: Context.TagClass<ContextServiceTag, "@interfere/react/Context", ContextService>;
9
+ declare class ContextServiceTag extends ContextServiceTag_base {}
10
+ declare const ContextServiceLive: Layer.Layer<ContextServiceTag, never, never>;
11
+ //#endregion
12
+ export { ContextService, ContextServiceLive, ContextServiceTag };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.layer.d.mts","names":[],"sources":["../../../src/effect/layers/context.layer.ts"],"sourcesContent":[],"mappings":";;;;UAKiB,cAAA;0BACS,MAAA,CAAO,OAAO;AADxC;AAEC,cAAA,sBAAA,kBAAA,kBAAA,EAAA,0BAAA,gBAAA,CAAA;cAEY,iBAAA,SAA0B,sBAAA;cAK1B,oBAAkB,KAAA,CAAA,MAAA"}
@@ -0,0 +1,14 @@
1
+ import { getContextProperties } from "../../core/runtime/context.mjs";
2
+ import { Context, Effect, Layer } from "effect";
3
+
4
+ //#region src/effect/layers/context.layer.ts
5
+ var ContextServiceTag = class extends Context.Tag("@interfere/react/Context")() {};
6
+ const ContextServiceLive = Layer.succeed(ContextServiceTag, (() => {
7
+ let cached = null;
8
+ return { getOnce: () => (cached ? Effect.succeed(cached) : getContextProperties().pipe(Effect.tap((ctx) => Effect.sync(() => {
9
+ cached = ctx;
10
+ })))).pipe(Effect.withSpan("context.getOnce")) };
11
+ })());
12
+
13
+ //#endregion
14
+ export { ContextServiceLive, ContextServiceTag };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.layer.mjs","names":["cached: ContextProperties | null"],"sources":["../../../src/effect/layers/context.layer.ts"],"sourcesContent":["import { Context, Effect, Layer } from \"effect\";\n\nimport type { ContextProperties } from \"../../core/runtime/context.js\";\nimport { getContextProperties } from \"../../core/runtime/context.js\";\n\nexport interface ContextService {\n readonly getOnce: () => Effect.Effect<ContextProperties>;\n}\n\nexport class ContextServiceTag extends Context.Tag(\"@interfere/react/Context\")<\n ContextServiceTag,\n ContextService\n>() {}\n\nexport const ContextServiceLive = Layer.succeed(\n ContextServiceTag,\n (() => {\n let cached: ContextProperties | null = null;\n\n return {\n getOnce: () =>\n (cached\n ? Effect.succeed(cached)\n : getContextProperties().pipe(\n Effect.tap((ctx) =>\n Effect.sync(() => {\n cached = ctx;\n })\n )\n )\n ).pipe(Effect.withSpan(\"context.getOnce\")),\n } satisfies ContextService;\n })()\n);\n"],"mappings":";;;;AASA,IAAa,oBAAb,cAAuC,QAAQ,IAAI,2BAA2B,EAG3E,CAAC;AAEJ,MAAa,qBAAqB,MAAM,QACtC,0BACO;CACL,IAAIA,SAAmC;AAEvC,QAAO,EACL,gBACG,SACG,OAAO,QAAQ,OAAO,GACtB,sBAAsB,CAAC,KACrB,OAAO,KAAK,QACV,OAAO,WAAW;AAChB,WAAS;GACT,CACH,CACF,EACH,KAAK,OAAO,SAAS,kBAAkB,CAAC,EAC7C;IACC,CACL"}
@@ -0,0 +1,21 @@
1
+ import { HttpError } from "../errors.mjs";
2
+ import { SdkConfig } from "./config.layer.mjs";
3
+ import { Context, Effect, Layer } from "effect";
4
+ import { Envelope } from "@interfere/types/sdk/envelope";
5
+
6
+ //#region src/effect/layers/http.layer.d.ts
7
+ interface HttpService {
8
+ readonly postEnvelopes: (envelopes: Envelope[]) => Effect.Effect<void, HttpError>;
9
+ }
10
+ declare const HttpServiceTag_base: Context.TagClass<HttpServiceTag, "@interfere/react/Http", HttpService>;
11
+ declare class HttpServiceTag extends HttpServiceTag_base {}
12
+ /**
13
+ * Creates an HTTP service layer for posting envelopes
14
+ */
15
+ interface HttpDeps {
16
+ readonly fetch?: typeof globalThis.fetch;
17
+ readonly timeoutMs?: number;
18
+ }
19
+ declare const HttpServiceLive: (config: SdkConfig, deps?: HttpDeps) => Layer.Layer<HttpServiceTag, never, never>;
20
+ //#endregion
21
+ export { HttpService, HttpServiceLive, HttpServiceTag };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.layer.d.mts","names":[],"sources":["../../../src/effect/layers/http.layer.ts"],"sourcesContent":[],"mappings":";;;;;;UAYiB,WAAA;sCAEF,eACR,MAAA,CAAO,aAAa;AAH3B;cAIC,mBAFc,kBAAA,eAAA,EAAA,uBAAA,aAAA,CAAA;AACY,cAGd,cAAA,SAAuB,mBAAA,CAHT;;AAC1B;;UAsDS,QAAA;0BACgB,UAAA,CAAW;;AArDrC;AAoDU,cAKG,eAJa,EAAW,CAAA,MAAK,EAIF,SAJE,EAAA,IAAA,CAAA,EAIgB,QAJhB,EAAA,GAIwB,KAAA,CAAA,KAJxB,CAIwB,cAJxB,EAAA,KAAA,EAAA,KAAA,CAAA"}
@@ -0,0 +1,113 @@
1
+ import { HttpError } from "../errors.mjs";
2
+ import { deriveIngestTarget } from "../../core/runtime/ingest-target.mjs";
3
+ import { Context, Effect, Layer } from "effect";
4
+ import { DEFAULT_TIMEOUT_MS, withTimeoutFail } from "@interfere/effect-utils/retry";
5
+
6
+ //#region src/effect/layers/http.layer.ts
7
+ var HttpServiceTag = class extends Context.Tag("@interfere/react/Http")() {};
8
+ /**
9
+ * Generates a W3C traceparent header
10
+ */
11
+ const generateTraceparent = () => {
12
+ return `00-${randomHex(16)}-${randomHex(8)}-01`;
13
+ };
14
+ function randomHex(bytes) {
15
+ const RANDOM_MAX = 256;
16
+ const HEX_BYTE_WIDTH = 2;
17
+ const buf = new Uint8Array(bytes);
18
+ if (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function") crypto.getRandomValues(buf);
19
+ else for (let i = 0; i < bytes; i += 1) buf[i] = Math.floor(Math.random() * RANDOM_MAX);
20
+ const HEX_BASE = 16;
21
+ return Array.from(buf).map((b) => b.toString(HEX_BASE).padStart(HEX_BYTE_WIDTH, "0")).join("");
22
+ }
23
+ /**
24
+ * Keepalive limits per Fetch spec (https://fetch.spec.whatwg.org/#http-network-or-cache-fetch):
25
+ * - If sum of body + inflight keepalive bytes > 64KB, returns network error
26
+ * - We use 60KB threshold to leave room for headers/overhead
27
+ * - Also limit concurrent keepalive requests to 15 (browser implementation detail)
28
+ */
29
+ const KEEPALIVE_BYTE_LIMIT = 6e4;
30
+ const KEEPALIVE_REQUEST_LIMIT = 15;
31
+ const HttpServiceLive = (config, deps) => {
32
+ let pendingBodySize = 0;
33
+ let pendingCount = 0;
34
+ return Layer.succeed(HttpServiceTag, { postEnvelopes: (envelopes) => {
35
+ const spanUrl = (() => {
36
+ try {
37
+ return deriveIngestTarget(config).url;
38
+ } catch {
39
+ return "<config-error>";
40
+ }
41
+ })();
42
+ return Effect.gen(function* () {
43
+ const target = yield* Effect.try({
44
+ try: () => deriveIngestTarget(config),
45
+ catch: (err) => new HttpError({
46
+ status: 0,
47
+ message: String(err instanceof Error ? err.message : err),
48
+ url: "<config-error>"
49
+ })
50
+ });
51
+ yield* Effect.logDebug("Sending batch to ingest").pipe(Effect.annotateLogs({
52
+ url: target.url,
53
+ envelopeCount: envelopes.length
54
+ }));
55
+ const headers = new Headers(target.headers);
56
+ const url = target.url;
57
+ headers.set("traceparent", generateTraceparent());
58
+ const TIMEOUT_MS = deps?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
59
+ const doFetch = deps?.fetch ?? fetch;
60
+ const HTTP_METHOD_POST = "POST";
61
+ const body = JSON.stringify(envelopes);
62
+ const requestSize = body.length;
63
+ pendingBodySize += requestSize;
64
+ pendingCount += 1;
65
+ const useKeepalive = pendingBodySize <= KEEPALIVE_BYTE_LIMIT && pendingCount <= KEEPALIVE_REQUEST_LIMIT;
66
+ const response = yield* withTimeoutFail(Effect.tryPromise({
67
+ try: async () => {
68
+ try {
69
+ return await doFetch(url, {
70
+ method: HTTP_METHOD_POST,
71
+ headers,
72
+ body,
73
+ keepalive: useKeepalive
74
+ });
75
+ } finally {
76
+ pendingBodySize -= requestSize;
77
+ pendingCount -= 1;
78
+ }
79
+ },
80
+ catch: (error) => new HttpError({
81
+ status: 0,
82
+ message: `Network error: ${String(error)}`,
83
+ url
84
+ })
85
+ }), TIMEOUT_MS, () => new HttpError({
86
+ status: 0,
87
+ message: "Network timeout",
88
+ url
89
+ }));
90
+ if (!response.ok) {
91
+ const body$1 = yield* Effect.promise(() => response.text()).pipe(Effect.orElse(() => Effect.succeed("")));
92
+ if (response.status === 422) return yield* Effect.fail(new HttpError({
93
+ status: response.status,
94
+ message: "Invalid envelopes (schema mismatch)",
95
+ url,
96
+ body: body$1
97
+ }));
98
+ return yield* Effect.fail(new HttpError({
99
+ status: response.status,
100
+ message: `Ingest failed: ${response.status} ${response.statusText}`,
101
+ url,
102
+ body: body$1
103
+ }));
104
+ }
105
+ }).pipe(Effect.withSpan("http.postEnvelopes", { attributes: {
106
+ envelopeCount: envelopes.length,
107
+ url: spanUrl
108
+ } }));
109
+ } });
110
+ };
111
+
112
+ //#endregion
113
+ export { HttpServiceLive, HttpServiceTag };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.layer.mjs","names":["body"],"sources":["../../../src/effect/layers/http.layer.ts"],"sourcesContent":["import {\n DEFAULT_TIMEOUT_MS,\n withTimeoutFail,\n} from \"@interfere/effect-utils/retry\";\nimport type { Envelope } from \"@interfere/types/sdk/envelope\";\n\nimport { Context, Effect, Layer } from \"effect\";\n\nimport { deriveIngestTarget } from \"../../core/runtime/ingest-target.js\";\nimport { HttpError } from \"../errors.js\";\nimport type { SdkConfig } from \"./config.layer.js\";\n\nexport interface HttpService {\n readonly postEnvelopes: (\n envelopes: Envelope[]\n ) => Effect.Effect<void, HttpError>;\n}\n\nexport class HttpServiceTag extends Context.Tag(\"@interfere/react/Http\")<\n HttpServiceTag,\n HttpService\n>() {}\n\n/**\n * Generates a W3C traceparent header\n */\nconst generateTraceparent = (): string => {\n const version = \"00\";\n const TRACE_ID_BYTES = 16;\n const SPAN_ID_BYTES = 8;\n const traceId = randomHex(TRACE_ID_BYTES);\n const spanId = randomHex(SPAN_ID_BYTES);\n const flags = \"01\";\n return `${version}-${traceId}-${spanId}-${flags}`;\n};\n\nfunction randomHex(bytes: number): string {\n const RANDOM_MAX = 256;\n const HEX_BYTE_WIDTH = 2;\n const buf = new Uint8Array(bytes);\n\n if (\n typeof crypto !== \"undefined\" &&\n typeof crypto.getRandomValues === \"function\"\n ) {\n crypto.getRandomValues(buf);\n } else {\n for (let i = 0; i < bytes; i += 1) {\n buf[i] = Math.floor(Math.random() * RANDOM_MAX);\n }\n }\n\n const HEX_BASE = 16;\n return Array.from(buf)\n .map((b) => b.toString(HEX_BASE).padStart(HEX_BYTE_WIDTH, \"0\"))\n .join(\"\");\n}\n\n/**\n * Keepalive limits per Fetch spec (https://fetch.spec.whatwg.org/#http-network-or-cache-fetch):\n * - If sum of body + inflight keepalive bytes > 64KB, returns network error\n * - We use 60KB threshold to leave room for headers/overhead\n * - Also limit concurrent keepalive requests to 15 (browser implementation detail)\n */\nconst KEEPALIVE_BYTE_LIMIT = 60_000;\nconst KEEPALIVE_REQUEST_LIMIT = 15; // Arbitrary limit\n\n/**\n * Creates an HTTP service layer for posting envelopes\n */\ninterface HttpDeps {\n readonly fetch?: typeof globalThis.fetch;\n readonly timeoutMs?: number;\n}\n\nexport const HttpServiceLive = (config: SdkConfig, deps?: HttpDeps) => {\n // Track pending keepalive request state across all concurrent requests.\n // These are closure variables that persist for the lifetime of the layer.\n let pendingBodySize = 0;\n let pendingCount = 0;\n\n return Layer.succeed(HttpServiceTag, {\n postEnvelopes: (envelopes: Envelope[]) => {\n const spanUrl = (() => {\n try {\n return deriveIngestTarget(config).url;\n } catch {\n return \"<config-error>\";\n }\n })();\n\n return Effect.gen(function* () {\n const target = yield* Effect.try({\n try: () => deriveIngestTarget(config),\n catch: (err) =>\n new HttpError({\n status: 0,\n message: String(err instanceof Error ? err.message : err),\n url: \"<config-error>\",\n }),\n });\n\n yield* Effect.logDebug(\"Sending batch to ingest\").pipe(\n Effect.annotateLogs({\n url: target.url,\n envelopeCount: envelopes.length,\n })\n );\n\n const headers = new Headers(target.headers);\n const url = target.url;\n\n // Add traceparent header\n headers.set(\"traceparent\", generateTraceparent());\n\n // Send the request with timeout\n const TIMEOUT_MS = deps?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const doFetch = deps?.fetch ?? fetch;\n const HTTP_METHOD_POST = \"POST\" as const;\n\n const body = JSON.stringify(envelopes);\n const requestSize = body.length;\n\n // Track this request's size for keepalive limit calculation\n pendingBodySize += requestSize;\n pendingCount += 1;\n\n // Keepalive allows requests to complete even when navigating away, but has limits:\n // - Per Fetch spec, if sum of inflight keepalive bytes > 64KB, it fails with network error\n // - The limit is aggregate across ALL concurrent keepalive requests, not per-request\n // - Caused \"Failed to fetch\" (status 0) errors in production when batches were large\n // - We only enable keepalive when under both size and count limits\n // See: https://fetch.spec.whatwg.org/#http-network-or-cache-fetch (step 8.10.5)\n const useKeepalive =\n pendingBodySize <= KEEPALIVE_BYTE_LIMIT &&\n pendingCount <= KEEPALIVE_REQUEST_LIMIT;\n\n const response = yield* withTimeoutFail(\n Effect.tryPromise({\n try: async () => {\n try {\n return await doFetch(url, {\n method: HTTP_METHOD_POST,\n headers,\n body,\n keepalive: useKeepalive,\n });\n } finally {\n // Always decrement counters when request completes (success or failure)\n pendingBodySize -= requestSize;\n pendingCount -= 1;\n }\n },\n catch: (error) =>\n new HttpError({\n status: 0,\n message: `Network error: ${String(error)}`,\n url,\n }),\n }),\n TIMEOUT_MS,\n () =>\n new HttpError({\n status: 0,\n message: \"Network timeout\",\n url,\n })\n );\n\n if (!response.ok) {\n const body = yield* Effect.promise(() => response.text()).pipe(\n Effect.orElse(() => Effect.succeed(\"\"))\n );\n\n // If the server tells us the envelopes are malformed, treat this as a\n // permanent failure so the queue layer can drop them instead of retrying.\n if (response.status === 422) {\n return yield* Effect.fail(\n new HttpError({\n status: response.status,\n message: \"Invalid envelopes (schema mismatch)\",\n url,\n body,\n })\n );\n }\n\n return yield* Effect.fail(\n new HttpError({\n status: response.status,\n message: `Ingest failed: ${response.status} ${response.statusText}`,\n url,\n body,\n })\n );\n }\n }).pipe(\n Effect.withSpan(\"http.postEnvelopes\", {\n attributes: {\n envelopeCount: envelopes.length,\n url: spanUrl,\n },\n })\n );\n },\n });\n};\n"],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { ConfigTag } from "../tags.mjs";
2
+ import { HttpServiceTag } from "./http.layer.mjs";
3
+ import { Context, Effect, Layer, Scope } from "effect";
4
+ import { CircuitBreakerState } from "@interfere/effect-utils/circuit-breaker";
5
+ import { Envelope } from "@interfere/types/sdk/envelope";
6
+
7
+ //#region src/effect/layers/queue.layer.d.ts
8
+ interface QueueMetrics {
9
+ readonly queueDepth: number;
10
+ readonly successCount: number;
11
+ readonly failureCount: number;
12
+ readonly circuitBreakerState: CircuitBreakerState;
13
+ }
14
+ interface QueueService {
15
+ readonly add: (envelope: Envelope) => Effect.Effect<void>;
16
+ readonly size: () => Effect.Effect<number>;
17
+ readonly flush: () => Effect.Effect<void>;
18
+ readonly boundedFlush: (timeoutMs: number) => Effect.Effect<void>;
19
+ readonly startBatchProcessor: () => Effect.Effect<void, never, Scope.Scope>;
20
+ readonly setReady: (ready: boolean) => Effect.Effect<void>;
21
+ readonly getMetrics: () => Effect.Effect<QueueMetrics>;
22
+ }
23
+ declare const QueueServiceTag_base: Context.TagClass<QueueServiceTag, "@interfere/react/Queue", QueueService>;
24
+ declare class QueueServiceTag extends QueueServiceTag_base {}
25
+ /**
26
+ * Creates the queue service layer
27
+ */
28
+ declare const QueueServiceLive: Layer.Layer<QueueServiceTag, never, ConfigTag | HttpServiceTag>;
29
+ //#endregion
30
+ export { QueueMetrics, QueueService, QueueServiceLive, QueueServiceTag };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.layer.d.mts","names":[],"sources":["../../../src/effect/layers/queue.layer.ts"],"sourcesContent":[],"mappings":";;;;;;;UA4CiB,YAAA;;EAAA,SAAA,YAAY,EAAA,MAIG;EAGf,SAAA,YAAY,EAAA,MAAA;EACF,SAAA,mBAAA,EAJK,mBAIL;;AACJ,UAFN,YAAA,CAEa;EACN,SAAO,GAAA,EAAA,CAAA,QAAA,EAFJ,QAEI,EAAA,GAFS,MAAA,CAAO,MAEhB,CAAA,IAAA,CAAA;EACiB,SAAO,IAAA,EAAA,GAAA,GAFhC,MAAA,CAAO,MAEyB,CAAA,MAAA,CAAA;EACU,SAAM,KAAA,EAAA,GAAA,GAF/C,MAAA,CAAO,MAEwC,CAAA,IAAA,CAAA;EAAjC,SAAO,YAAA,EAAA,CAAA,SAAA,EAAA,MAAA,EAAA,GADG,MAAA,CAAO,MACV,CAAA,IAAA,CAAA;EACJ,SAAO,mBAAA,EAAA,GAAA,GADV,MAAA,CAAO,MACG,CAAA,IAAA,EAAA,KAAA,EADiB,KAAA,CAAM,KACvB,CAAA;EACL,SAAA,QAAA,EAAA,CAAA,KAAA,EAAA,OAAA,EAAA,GADF,MAAA,CAAO,MACL,CAAA,IAAA,CAAA;EAAd,SAAO,UAAA,EAAA,GAAA,GAAP,MAAA,CAAO,MAAA,CAAO,YAAP,CAAA;;AACnC,cAAA,oBAAA,kBAAA,gBAAA,EAAA,wBAAA,cAAA,CAAA;cAEY,eAAA,SAAwB,oBAAA;;;AAArC;AA0Ba,cAAA,gBA8aZ,EA9a4B,KAAA,CAAA,KA8a5B,CA9a4B,eA8a5B,EAAA,KAAA,EA9a4B,SA8a5B,GA9a4B,cA8a5B,CAAA"}