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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. package/dist/error-boundary.d.mts +27 -0
  2. package/dist/error-boundary.d.mts.map +1 -0
  3. package/dist/error-boundary.mjs +42 -0
  4. package/dist/error-boundary.mjs.map +1 -0
  5. package/dist/internal/client.d.mts +13 -0
  6. package/dist/internal/client.d.mts.map +1 -0
  7. package/dist/internal/client.mjs +80 -0
  8. package/dist/internal/client.mjs.map +1 -0
  9. package/dist/internal/config.d.mts +9 -0
  10. package/dist/internal/config.d.mts.map +1 -0
  11. package/dist/internal/config.mjs +27 -0
  12. package/dist/internal/config.mjs.map +1 -0
  13. package/dist/internal/context.d.mts +6 -0
  14. package/dist/internal/context.d.mts.map +1 -0
  15. package/dist/internal/context.mjs +32 -0
  16. package/dist/internal/context.mjs.map +1 -0
  17. package/dist/internal/envelope.d.mts +14 -0
  18. package/dist/internal/envelope.d.mts.map +1 -0
  19. package/dist/internal/envelope.mjs +20 -0
  20. package/dist/internal/envelope.mjs.map +1 -0
  21. package/dist/internal/errors.d.mts +4 -0
  22. package/dist/internal/errors.d.mts.map +1 -0
  23. package/dist/internal/errors.mjs +4 -0
  24. package/dist/internal/errors.mjs.map +1 -0
  25. package/dist/internal/sw.d.mts +4 -0
  26. package/dist/internal/sw.d.mts.map +1 -0
  27. package/dist/internal/sw.mjs +10 -0
  28. package/dist/internal/sw.mjs.map +1 -0
  29. package/dist/plugins/errors.d.mts +6 -0
  30. package/dist/plugins/errors.d.mts.map +1 -0
  31. package/dist/plugins/errors.mjs +59 -0
  32. package/dist/plugins/errors.mjs.map +1 -0
  33. package/dist/plugins/lib/loader.d.mts +9 -0
  34. package/dist/plugins/lib/loader.d.mts.map +1 -0
  35. package/dist/plugins/lib/loader.mjs +47 -0
  36. package/dist/plugins/lib/loader.mjs.map +1 -0
  37. package/dist/plugins/lib/types.d.mts +14 -0
  38. package/dist/plugins/lib/types.d.mts.map +1 -0
  39. package/dist/plugins/lib/types.mjs +1 -0
  40. package/dist/plugins/pages.d.mts +6 -0
  41. package/dist/plugins/pages.d.mts.map +1 -0
  42. package/dist/plugins/pages.mjs +102 -0
  43. package/dist/plugins/pages.mjs.map +1 -0
  44. package/dist/plugins/rage-clicks.d.mts +6 -0
  45. package/dist/plugins/rage-clicks.d.mts.map +1 -0
  46. package/dist/plugins/rage-clicks.mjs +53 -0
  47. package/dist/plugins/rage-clicks.mjs.map +1 -0
  48. package/dist/plugins/replay.d.mts +6 -0
  49. package/dist/plugins/replay.d.mts.map +1 -0
  50. package/dist/plugins/replay.mjs +62 -0
  51. package/dist/plugins/replay.mjs.map +1 -0
  52. package/dist/provider.d.mts +17 -11
  53. package/dist/provider.d.mts.map +1 -1
  54. package/dist/provider.mjs +18 -17
  55. package/dist/provider.mjs.map +1 -1
  56. package/dist/tracking/api.d.mts +22 -0
  57. package/dist/tracking/api.d.mts.map +1 -0
  58. package/dist/tracking/api.mjs +88 -0
  59. package/dist/tracking/api.mjs.map +1 -0
  60. package/dist/tracking/session.d.mts +19 -0
  61. package/dist/tracking/session.d.mts.map +1 -0
  62. package/dist/tracking/session.mjs +92 -0
  63. package/dist/tracking/session.mjs.map +1 -0
  64. package/dist/tracking/visitor.d.mts +6 -0
  65. package/dist/tracking/visitor.d.mts.map +1 -0
  66. package/dist/tracking/visitor.mjs +35 -0
  67. package/dist/tracking/visitor.mjs.map +1 -0
  68. package/dist/transport/http.d.mts +15 -0
  69. package/dist/transport/http.d.mts.map +1 -0
  70. package/dist/transport/http.mjs +56 -0
  71. package/dist/transport/http.mjs.map +1 -0
  72. package/dist/transport/queue.d.mts +25 -0
  73. package/dist/transport/queue.d.mts.map +1 -0
  74. package/dist/transport/queue.mjs +60 -0
  75. package/dist/transport/queue.mjs.map +1 -0
  76. package/dist/util/log.d.mts +13 -0
  77. package/dist/util/log.d.mts.map +1 -0
  78. package/dist/util/log.mjs +37 -0
  79. package/dist/util/log.mjs.map +1 -0
  80. package/package.json +47 -70
  81. package/dist/client.d.mts +0 -15
  82. package/dist/client.d.mts.map +0 -1
  83. package/dist/client.mjs +0 -75
  84. package/dist/client.mjs.map +0 -1
  85. package/dist/core/events/event-registry.d.mts +0 -23
  86. package/dist/core/events/event-registry.d.mts.map +0 -1
  87. package/dist/core/events/event-registry.mjs +0 -32
  88. package/dist/core/events/event-registry.mjs.map +0 -1
  89. package/dist/core/events/plugin-event-types.d.mts +0 -92
  90. package/dist/core/events/plugin-event-types.d.mts.map +0 -1
  91. package/dist/core/events/plugin-event-types.mjs +0 -25
  92. package/dist/core/events/plugin-event-types.mjs.map +0 -1
  93. package/dist/core/plugins/dom-utils.d.mts +0 -9
  94. package/dist/core/plugins/dom-utils.d.mts.map +0 -1
  95. package/dist/core/plugins/dom-utils.mjs +0 -25
  96. package/dist/core/plugins/dom-utils.mjs.map +0 -1
  97. package/dist/core/plugins/impl/ai-summary.d.mts +0 -6
  98. package/dist/core/plugins/impl/ai-summary.d.mts.map +0 -1
  99. package/dist/core/plugins/impl/ai-summary.mjs +0 -122
  100. package/dist/core/plugins/impl/ai-summary.mjs.map +0 -1
  101. package/dist/core/plugins/impl/errors.d.mts +0 -9
  102. package/dist/core/plugins/impl/errors.d.mts.map +0 -1
  103. package/dist/core/plugins/impl/errors.mjs +0 -153
  104. package/dist/core/plugins/impl/errors.mjs.map +0 -1
  105. package/dist/core/plugins/impl/page-events.d.mts +0 -15
  106. package/dist/core/plugins/impl/page-events.d.mts.map +0 -1
  107. package/dist/core/plugins/impl/page-events.mjs +0 -131
  108. package/dist/core/plugins/impl/page-events.mjs.map +0 -1
  109. package/dist/core/plugins/impl/rage-click.d.mts +0 -6
  110. package/dist/core/plugins/impl/rage-click.d.mts.map +0 -1
  111. package/dist/core/plugins/impl/rage-click.mjs +0 -53
  112. package/dist/core/plugins/impl/rage-click.mjs.map +0 -1
  113. package/dist/core/plugins/impl/replay.d.mts +0 -9
  114. package/dist/core/plugins/impl/replay.d.mts.map +0 -1
  115. package/dist/core/plugins/impl/replay.mjs +0 -144
  116. package/dist/core/plugins/impl/replay.mjs.map +0 -1
  117. package/dist/core/plugins/impl/server-tracing.d.mts +0 -7
  118. package/dist/core/plugins/impl/server-tracing.d.mts.map +0 -1
  119. package/dist/core/plugins/impl/server-tracing.mjs +0 -160
  120. package/dist/core/plugins/impl/server-tracing.mjs.map +0 -1
  121. package/dist/core/plugins/plugin-event-system.d.mts +0 -47
  122. package/dist/core/plugins/plugin-event-system.d.mts.map +0 -1
  123. package/dist/core/plugins/plugin-event-system.mjs +0 -75
  124. package/dist/core/plugins/plugin-event-system.mjs.map +0 -1
  125. package/dist/core/plugins/plugin-loader.d.mts +0 -22
  126. package/dist/core/plugins/plugin-loader.d.mts.map +0 -1
  127. package/dist/core/plugins/plugin-loader.mjs +0 -142
  128. package/dist/core/plugins/plugin-loader.mjs.map +0 -1
  129. package/dist/core/runtime/config.d.mts +0 -14
  130. package/dist/core/runtime/config.d.mts.map +0 -1
  131. package/dist/core/runtime/config.mjs +0 -39
  132. package/dist/core/runtime/config.mjs.map +0 -1
  133. package/dist/core/runtime/context.d.mts +0 -25
  134. package/dist/core/runtime/context.d.mts.map +0 -1
  135. package/dist/core/runtime/context.mjs +0 -48
  136. package/dist/core/runtime/context.mjs.map +0 -1
  137. package/dist/core/runtime/ingest-target.d.mts +0 -10
  138. package/dist/core/runtime/ingest-target.d.mts.map +0 -1
  139. package/dist/core/runtime/ingest-target.mjs +0 -15
  140. package/dist/core/runtime/ingest-target.mjs.map +0 -1
  141. package/dist/core/schemas.d.mts +0 -85
  142. package/dist/core/schemas.d.mts.map +0 -1
  143. package/dist/core/schemas.mjs +0 -1
  144. package/dist/effect/build-envelope.d.mts +0 -9
  145. package/dist/effect/build-envelope.d.mts.map +0 -1
  146. package/dist/effect/build-envelope.mjs +0 -29
  147. package/dist/effect/build-envelope.mjs.map +0 -1
  148. package/dist/effect/errors.d.mts +0 -36
  149. package/dist/effect/errors.d.mts.map +0 -1
  150. package/dist/effect/errors.mjs +0 -10
  151. package/dist/effect/errors.mjs.map +0 -1
  152. package/dist/effect/layers/config.layer.d.mts +0 -13
  153. package/dist/effect/layers/config.layer.d.mts.map +0 -1
  154. package/dist/effect/layers/config.layer.mjs +0 -21
  155. package/dist/effect/layers/config.layer.mjs.map +0 -1
  156. package/dist/effect/layers/context.layer.d.mts +0 -12
  157. package/dist/effect/layers/context.layer.d.mts.map +0 -1
  158. package/dist/effect/layers/context.layer.mjs +0 -14
  159. package/dist/effect/layers/context.layer.mjs.map +0 -1
  160. package/dist/effect/layers/http.layer.d.mts +0 -21
  161. package/dist/effect/layers/http.layer.d.mts.map +0 -1
  162. package/dist/effect/layers/http.layer.mjs +0 -113
  163. package/dist/effect/layers/http.layer.mjs.map +0 -1
  164. package/dist/effect/layers/queue.layer.d.mts +0 -30
  165. package/dist/effect/layers/queue.layer.d.mts.map +0 -1
  166. package/dist/effect/layers/queue.layer.mjs +0 -232
  167. package/dist/effect/layers/queue.layer.mjs.map +0 -1
  168. package/dist/effect/layers/session.layer.d.mts +0 -26
  169. package/dist/effect/layers/session.layer.d.mts.map +0 -1
  170. package/dist/effect/layers/session.layer.mjs +0 -126
  171. package/dist/effect/layers/session.layer.mjs.map +0 -1
  172. package/dist/effect/layers/storage.layer.d.mts +0 -19
  173. package/dist/effect/layers/storage.layer.d.mts.map +0 -1
  174. package/dist/effect/layers/storage.layer.mjs +0 -200
  175. package/dist/effect/layers/storage.layer.mjs.map +0 -1
  176. package/dist/effect/layers/tracer.layer.d.mts +0 -9
  177. package/dist/effect/layers/tracer.layer.d.mts.map +0 -1
  178. package/dist/effect/layers/tracer.layer.mjs +0 -11
  179. package/dist/effect/layers/tracer.layer.mjs.map +0 -1
  180. package/dist/effect/runtime-services.d.mts +0 -22
  181. package/dist/effect/runtime-services.d.mts.map +0 -1
  182. package/dist/effect/runtime-services.mjs +0 -76
  183. package/dist/effect/runtime-services.mjs.map +0 -1
  184. package/dist/effect/tags.d.mts +0 -50
  185. package/dist/effect/tags.d.mts.map +0 -1
  186. package/dist/effect/tags.mjs +0 -7
  187. package/dist/effect/tags.mjs.map +0 -1
  188. package/dist/hooks/use-runtime-and-plugins.d.mts +0 -7
  189. package/dist/hooks/use-runtime-and-plugins.d.mts.map +0 -1
  190. package/dist/hooks/use-runtime-and-plugins.mjs +0 -153
  191. package/dist/hooks/use-runtime-and-plugins.mjs.map +0 -1
  192. package/dist/hooks/use-session.d.mts +0 -40
  193. package/dist/hooks/use-session.d.mts.map +0 -1
  194. package/dist/hooks/use-session.mjs +0 -96
  195. package/dist/hooks/use-session.mjs.map +0 -1
  196. package/dist/package.mjs +0 -100
  197. package/dist/package.mjs.map +0 -1
  198. package/dist/server/auth.d.mts +0 -11
  199. package/dist/server/auth.d.mts.map +0 -1
  200. package/dist/server/auth.mjs +0 -36
  201. package/dist/server/auth.mjs.map +0 -1
  202. package/dist/server/capture.d.mts +0 -18
  203. package/dist/server/capture.d.mts.map +0 -1
  204. package/dist/server/capture.mjs +0 -105
  205. package/dist/server/capture.mjs.map +0 -1
@@ -1,26 +0,0 @@
1
- import { Context, Effect, Layer, Option } from "effect";
2
-
3
- //#region src/effect/layers/session.layer.d.ts
4
- interface SessionService {
5
- readonly getSessionId: () => Effect.Effect<Option.Option<string>>;
6
- readonly ensureWindowId: () => Effect.Effect<string | null>;
7
- readonly updateActivity: () => Effect.Effect<void>;
8
- readonly resetSession: () => Effect.Effect<void>;
9
- readonly whenSessionReady: (options?: {
10
- timeout?: number;
11
- signal?: AbortSignal;
12
- }) => Effect.Effect<string, Error>;
13
- readonly getSessionDebug: () => Effect.Effect<{
14
- sessionId: string | null;
15
- sessionStartTimestamp: number | null;
16
- lastActivityTimestamp: number | null;
17
- sessionTimeoutMs: number;
18
- sessionAge: number | undefined;
19
- timeSinceLastActivity: number | undefined;
20
- }>;
21
- }
22
- declare const SessionServiceTag_base: Context.TagClass<SessionServiceTag, "@interfere/react/Session", SessionService>;
23
- declare class SessionServiceTag extends SessionServiceTag_base {}
24
- declare const SessionServiceLive: Layer.Layer<SessionServiceTag, never, never>;
25
- //#endregion
26
- export { SessionService, SessionServiceLive, SessionServiceTag };
@@ -1 +0,0 @@
1
- {"version":3,"file":"session.layer.d.mts","names":[],"sources":["../../../src/effect/layers/session.layer.ts"],"sourcesContent":[],"mappings":";;;UA+CiB,cAAA;+BACc,MAAA,CAAO,OAAO,MAAA,CAAO;EADnC,SAAA,cAAc,EAAA,GAAA,GAEE,MAAA,CAAO,MAFT,CAAA,MAAA,GAAA,IAAA,CAAA;EACc,SAAO,cAAA,EAAA,GAAA,GAEnB,MAAA,CAAO,MAFY,CAAA,IAAA,CAAA;EAArB,SAAO,YAAA,EAAA,GAAA,GAGP,MAAA,CAAO,MAHA,CAAA,IAAA,CAAA;EACL,SAAO,gBAAA,EAAA,CAAA,OAK3B,CAL2B,EAAA;IACA,OAAA,CAAA,EAAA,MAAA;IACF,MAAA,CAAA,EAGzB,WAHyB;EAGzB,CAAA,EAAA,GACL,MAAA,CAAO,MADF,CAAA,MAAA,EACiB,KADjB,CAAA;EACiB,SAAA,eAAA,EAAA,GAAA,GACI,MAAA,CAAO,MADX,CAAA;IAAf,SAAA,EAAA,MAAA,GAAA,IAAA;IAC0B,qBAAA,EAAA,MAAA,GAAA,IAAA;IAAM,qBAAA,EAAA,MAAA,GAAA,IAAA;IAQ9C,gBAAA,EAAA,MAAA;;;;;AAED,cAFC,sBAE8B,kBAAQ,kBAGpC,EAAA,0BAAA,gBAAA,CAAA;AAwCU,cA3CA,iBAAA,SAA0B,sBAAA,CA2CR;cAAlB,oBAAkB,KAAA,CAAA,MAAA"}
@@ -1,126 +0,0 @@
1
- import { Context, Duration, Effect, Layer, Option } from "effect";
2
- import { v7 } from "uuid";
3
- import { nanoid } from "nanoid";
4
-
5
- //#region src/effect/layers/session.layer.ts
6
- const STORAGE_KEYS = {
7
- sessionId: "__interfere_session_id__",
8
- sessionStart: "__interfere_session_start__",
9
- lastActivity: "__interfere_last_activity__",
10
- windowId: "__interfere_window_id__"
11
- };
12
- const SESSION_TIMEOUT_MS = 18e5;
13
- const DEFAULT_TIMEOUT_MS = 3e4;
14
- const WINDOW_ID_LENGTH = 10;
15
- const PROBE_KEY = "__interfere_probe__";
16
- const PROBE_VALUE = "1";
17
- let sessionId = null;
18
- let windowId = null;
19
- let sessionStartTimestamp = null;
20
- let lastActivityTimestamp = null;
21
- function safeNow() {
22
- return Date.now();
23
- }
24
- function canUseStorage() {
25
- try {
26
- if (typeof window === "undefined" || !window.localStorage) return false;
27
- window.localStorage.setItem(PROBE_KEY, PROBE_VALUE);
28
- window.localStorage.removeItem(PROBE_KEY);
29
- return true;
30
- } catch {
31
- return false;
32
- }
33
- }
34
- function newSessionId() {
35
- return v7();
36
- }
37
- var SessionServiceTag = class extends Context.Tag("@interfere/react/Session")() {};
38
- const getSessionIdImpl = () => Effect.sync(() => {
39
- if (typeof window === "undefined") return Option.none();
40
- if (sessionId) return Option.some(sessionId);
41
- const now = safeNow();
42
- const storage = canUseStorage() ? window.localStorage : null;
43
- const stored = storage?.getItem(STORAGE_KEYS.sessionId) ?? null;
44
- const start = Number(storage?.getItem(STORAGE_KEYS.sessionStart) ?? "0");
45
- const last = Number(storage?.getItem(STORAGE_KEYS.lastActivity) ?? "0");
46
- const expired = last > 0 && now - last > SESSION_TIMEOUT_MS;
47
- if (!stored || expired) {
48
- sessionId = newSessionId();
49
- sessionStartTimestamp = now;
50
- lastActivityTimestamp = now;
51
- storage?.setItem(STORAGE_KEYS.sessionId, sessionId);
52
- storage?.setItem(STORAGE_KEYS.sessionStart, String(sessionStartTimestamp));
53
- storage?.setItem(STORAGE_KEYS.lastActivity, String(lastActivityTimestamp));
54
- return Option.some(sessionId);
55
- }
56
- sessionId = stored;
57
- sessionStartTimestamp = start || now;
58
- lastActivityTimestamp = last || now;
59
- return Option.some(sessionId);
60
- });
61
- const SessionServiceLive = Layer.succeed(SessionServiceTag, {
62
- ensureWindowId: () => Effect.sync(() => {
63
- if (typeof window === "undefined") return null;
64
- if (windowId) return windowId;
65
- const storage = canUseStorage() ? window.localStorage : null;
66
- windowId = storage?.getItem(STORAGE_KEYS.windowId) ?? null ?? `win_${nanoid(WINDOW_ID_LENGTH)}`;
67
- storage?.setItem(STORAGE_KEYS.windowId, windowId);
68
- return windowId;
69
- }),
70
- getSessionId: getSessionIdImpl,
71
- updateActivity: () => Effect.sync(() => {
72
- if (typeof window === "undefined") return;
73
- const storage = canUseStorage() ? window.localStorage : null;
74
- lastActivityTimestamp = safeNow();
75
- storage?.setItem(STORAGE_KEYS.lastActivity, String(lastActivityTimestamp));
76
- }),
77
- resetSession: () => Effect.sync(() => {
78
- if (typeof window === "undefined") return;
79
- const storage = canUseStorage() ? window.localStorage : null;
80
- sessionId = newSessionId();
81
- sessionStartTimestamp = safeNow();
82
- lastActivityTimestamp = sessionStartTimestamp;
83
- storage?.setItem(STORAGE_KEYS.sessionId, sessionId);
84
- storage?.setItem(STORAGE_KEYS.sessionStart, String(sessionStartTimestamp));
85
- storage?.setItem(STORAGE_KEYS.lastActivity, String(lastActivityTimestamp));
86
- }),
87
- whenSessionReady: (options = {}) => {
88
- const POLL_INTERVAL_MS = 250;
89
- const MAX_TIMEOUT = options.timeout ?? DEFAULT_TIMEOUT_MS;
90
- const abortEffect = options.signal ? Effect.async((resume) => {
91
- const signal = options.signal;
92
- if (!signal) return;
93
- if (signal.aborted) {
94
- resume(Effect.die(/* @__PURE__ */ new Error("Aborted")));
95
- return;
96
- }
97
- const handler = () => resume(Effect.die(/* @__PURE__ */ new Error("Aborted")));
98
- signal.addEventListener("abort", handler, { once: true });
99
- return Effect.sync(() => {
100
- signal.removeEventListener("abort", handler);
101
- });
102
- }) : Effect.never;
103
- const pollOnce = Effect.suspend(() => Effect.gen(function* () {
104
- const sidOpt = yield* getSessionIdImpl();
105
- if (Option.isSome(sidOpt)) return sidOpt.value;
106
- yield* Effect.sleep(Duration.millis(POLL_INTERVAL_MS));
107
- return yield* pollOnce;
108
- }));
109
- const poll = pollOnce.pipe(Effect.timeoutFail({
110
- onTimeout: () => /* @__PURE__ */ new Error("Session ID not available within timeout"),
111
- duration: Duration.millis(MAX_TIMEOUT)
112
- }));
113
- return Effect.race(poll, abortEffect);
114
- },
115
- getSessionDebug: () => Effect.sync(() => ({
116
- sessionId,
117
- sessionStartTimestamp,
118
- lastActivityTimestamp,
119
- sessionTimeoutMs: SESSION_TIMEOUT_MS,
120
- sessionAge: sessionStartTimestamp ? safeNow() - sessionStartTimestamp : void 0,
121
- timeSinceLastActivity: lastActivityTimestamp ? safeNow() - lastActivityTimestamp : void 0
122
- }))
123
- });
124
-
125
- //#endregion
126
- export { SessionServiceLive, SessionServiceTag };
@@ -1 +0,0 @@
1
- {"version":3,"file":"session.layer.mjs","names":["sessionId: string | null","windowId: string | null","sessionStartTimestamp: number | null","lastActivityTimestamp: number | null","uuidv7","pollOnce: Effect.Effect<string>"],"sources":["../../../src/effect/layers/session.layer.ts"],"sourcesContent":["import { Context, Duration, Effect, Layer, Option } from \"effect\";\nimport { nanoid } from \"nanoid\";\nimport { v7 as uuidv7 } from \"uuid\";\n\n// Constants\nconst STORAGE_KEYS = {\n sessionId: \"__interfere_session_id__\",\n sessionStart: \"__interfere_session_start__\",\n lastActivity: \"__interfere_last_activity__\",\n windowId: \"__interfere_window_id__\",\n} as const;\n\nconst SESSION_TIMEOUT_MS = 1_800_000; // 30 minutes\nconst DEFAULT_TIMEOUT_MS = 30_000; // 30 seconds\nconst WINDOW_ID_LENGTH = 10;\nconst PROBE_KEY = \"__interfere_probe__\";\nconst PROBE_VALUE = \"1\";\n\n// In-memory state\nlet sessionId: string | null = null;\nlet windowId: string | null = null;\nlet sessionStartTimestamp: number | null = null;\nlet lastActivityTimestamp: number | null = null;\n\n// Helpers\nfunction safeNow() {\n return Date.now();\n}\n\nfunction canUseStorage() {\n try {\n if (typeof window === \"undefined\" || !window.localStorage) {\n return false;\n }\n window.localStorage.setItem(PROBE_KEY, PROBE_VALUE);\n window.localStorage.removeItem(PROBE_KEY);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction newSessionId(): string {\n return uuidv7();\n}\n\n// Service type\nexport interface SessionService {\n readonly getSessionId: () => Effect.Effect<Option.Option<string>>;\n readonly ensureWindowId: () => Effect.Effect<string | null>;\n readonly updateActivity: () => Effect.Effect<void>;\n readonly resetSession: () => Effect.Effect<void>;\n readonly whenSessionReady: (options?: {\n timeout?: number;\n signal?: AbortSignal;\n }) => Effect.Effect<string, Error>;\n readonly getSessionDebug: () => Effect.Effect<{\n sessionId: string | null;\n sessionStartTimestamp: number | null;\n lastActivityTimestamp: number | null;\n sessionTimeoutMs: number;\n sessionAge: number | undefined;\n timeSinceLastActivity: number | undefined;\n }>;\n}\n\nexport class SessionServiceTag extends Context.Tag(\"@interfere/react/Session\")<\n SessionServiceTag,\n SessionService\n>() {}\n\n// Internal implementation functions\nconst getSessionIdImpl = () =>\n Effect.sync(() => {\n if (typeof window === \"undefined\") {\n return Option.none();\n }\n if (sessionId) {\n return Option.some(sessionId);\n }\n const now = safeNow();\n const storage = canUseStorage() ? window.localStorage : null;\n const stored = storage?.getItem(STORAGE_KEYS.sessionId) ?? null;\n const start = Number(storage?.getItem(STORAGE_KEYS.sessionStart) ?? \"0\");\n const last = Number(storage?.getItem(STORAGE_KEYS.lastActivity) ?? \"0\");\n const expired = last > 0 && now - last > SESSION_TIMEOUT_MS;\n\n if (!stored || expired) {\n sessionId = newSessionId();\n sessionStartTimestamp = now;\n lastActivityTimestamp = now;\n storage?.setItem(STORAGE_KEYS.sessionId, sessionId);\n storage?.setItem(\n STORAGE_KEYS.sessionStart,\n String(sessionStartTimestamp)\n );\n storage?.setItem(\n STORAGE_KEYS.lastActivity,\n String(lastActivityTimestamp)\n );\n return Option.some(sessionId);\n }\n\n sessionId = stored;\n sessionStartTimestamp = start || now;\n lastActivityTimestamp = last || now;\n return Option.some(sessionId);\n });\n\nexport const SessionServiceLive = Layer.succeed(SessionServiceTag, {\n ensureWindowId: () =>\n Effect.sync(() => {\n if (typeof window === \"undefined\") {\n return null;\n }\n if (windowId) {\n return windowId;\n }\n const storage = canUseStorage() ? window.localStorage : null;\n const existing = storage?.getItem(STORAGE_KEYS.windowId) ?? null;\n windowId = existing ?? `win_${nanoid(WINDOW_ID_LENGTH)}`;\n storage?.setItem(STORAGE_KEYS.windowId, windowId);\n return windowId;\n }),\n\n getSessionId: getSessionIdImpl,\n\n updateActivity: () =>\n Effect.sync(() => {\n if (typeof window === \"undefined\") {\n return;\n }\n const storage = canUseStorage() ? window.localStorage : null;\n lastActivityTimestamp = safeNow();\n storage?.setItem(\n STORAGE_KEYS.lastActivity,\n String(lastActivityTimestamp)\n );\n }),\n\n resetSession: () =>\n Effect.sync(() => {\n if (typeof window === \"undefined\") {\n return;\n }\n const storage = canUseStorage() ? window.localStorage : null;\n sessionId = newSessionId();\n sessionStartTimestamp = safeNow();\n lastActivityTimestamp = sessionStartTimestamp;\n storage?.setItem(STORAGE_KEYS.sessionId, sessionId);\n storage?.setItem(\n STORAGE_KEYS.sessionStart,\n String(sessionStartTimestamp)\n );\n storage?.setItem(\n STORAGE_KEYS.lastActivity,\n String(lastActivityTimestamp)\n );\n }),\n\n whenSessionReady: (options = {}) => {\n const POLL_INTERVAL_MS = 250;\n const MAX_TIMEOUT = options.timeout ?? DEFAULT_TIMEOUT_MS;\n\n const abortEffect = options.signal\n ? Effect.async<never>((resume) => {\n const signal = options.signal;\n if (!signal) {\n return;\n }\n\n if (signal.aborted) {\n resume(Effect.die(new Error(\"Aborted\")));\n return;\n }\n\n const handler = () => resume(Effect.die(new Error(\"Aborted\")));\n signal.addEventListener(\"abort\", handler, { once: true });\n return Effect.sync(() => {\n signal.removeEventListener(\"abort\", handler);\n });\n })\n : Effect.never;\n\n const pollOnce: Effect.Effect<string> = Effect.suspend(() =>\n Effect.gen(function* () {\n const sidOpt = yield* getSessionIdImpl();\n if (Option.isSome(sidOpt)) {\n return sidOpt.value;\n }\n yield* Effect.sleep(Duration.millis(POLL_INTERVAL_MS));\n return yield* pollOnce;\n })\n );\n\n const poll = pollOnce.pipe(\n Effect.timeoutFail({\n onTimeout: () => new Error(\"Session ID not available within timeout\"),\n duration: Duration.millis(MAX_TIMEOUT),\n })\n );\n\n return Effect.race(poll, abortEffect);\n },\n\n getSessionDebug: () =>\n Effect.sync(() => ({\n sessionId,\n sessionStartTimestamp,\n lastActivityTimestamp,\n sessionTimeoutMs: SESSION_TIMEOUT_MS,\n sessionAge: sessionStartTimestamp\n ? safeNow() - sessionStartTimestamp\n : undefined,\n timeSinceLastActivity: lastActivityTimestamp\n ? safeNow() - lastActivityTimestamp\n : undefined,\n })),\n} satisfies SessionService);\n"],"mappings":";;;;;AAKA,MAAM,eAAe;CACnB,WAAW;CACX,cAAc;CACd,cAAc;CACd,UAAU;CACX;AAED,MAAM,qBAAqB;AAC3B,MAAM,qBAAqB;AAC3B,MAAM,mBAAmB;AACzB,MAAM,YAAY;AAClB,MAAM,cAAc;AAGpB,IAAIA,YAA2B;AAC/B,IAAIC,WAA0B;AAC9B,IAAIC,wBAAuC;AAC3C,IAAIC,wBAAuC;AAG3C,SAAS,UAAU;AACjB,QAAO,KAAK,KAAK;;AAGnB,SAAS,gBAAgB;AACvB,KAAI;AACF,MAAI,OAAO,WAAW,eAAe,CAAC,OAAO,aAC3C,QAAO;AAET,SAAO,aAAa,QAAQ,WAAW,YAAY;AACnD,SAAO,aAAa,WAAW,UAAU;AACzC,SAAO;SACD;AACN,SAAO;;;AAIX,SAAS,eAAuB;AAC9B,QAAOC,IAAQ;;AAuBjB,IAAa,oBAAb,cAAuC,QAAQ,IAAI,2BAA2B,EAG3E,CAAC;AAGJ,MAAM,yBACJ,OAAO,WAAW;AAChB,KAAI,OAAO,WAAW,YACpB,QAAO,OAAO,MAAM;AAEtB,KAAI,UACF,QAAO,OAAO,KAAK,UAAU;CAE/B,MAAM,MAAM,SAAS;CACrB,MAAM,UAAU,eAAe,GAAG,OAAO,eAAe;CACxD,MAAM,SAAS,SAAS,QAAQ,aAAa,UAAU,IAAI;CAC3D,MAAM,QAAQ,OAAO,SAAS,QAAQ,aAAa,aAAa,IAAI,IAAI;CACxE,MAAM,OAAO,OAAO,SAAS,QAAQ,aAAa,aAAa,IAAI,IAAI;CACvE,MAAM,UAAU,OAAO,KAAK,MAAM,OAAO;AAEzC,KAAI,CAAC,UAAU,SAAS;AACtB,cAAY,cAAc;AAC1B,0BAAwB;AACxB,0BAAwB;AACxB,WAAS,QAAQ,aAAa,WAAW,UAAU;AACnD,WAAS,QACP,aAAa,cACb,OAAO,sBAAsB,CAC9B;AACD,WAAS,QACP,aAAa,cACb,OAAO,sBAAsB,CAC9B;AACD,SAAO,OAAO,KAAK,UAAU;;AAG/B,aAAY;AACZ,yBAAwB,SAAS;AACjC,yBAAwB,QAAQ;AAChC,QAAO,OAAO,KAAK,UAAU;EAC7B;AAEJ,MAAa,qBAAqB,MAAM,QAAQ,mBAAmB;CACjE,sBACE,OAAO,WAAW;AAChB,MAAI,OAAO,WAAW,YACpB,QAAO;AAET,MAAI,SACF,QAAO;EAET,MAAM,UAAU,eAAe,GAAG,OAAO,eAAe;AAExD,aADiB,SAAS,QAAQ,aAAa,SAAS,IAAI,QACrC,OAAO,OAAO,iBAAiB;AACtD,WAAS,QAAQ,aAAa,UAAU,SAAS;AACjD,SAAO;GACP;CAEJ,cAAc;CAEd,sBACE,OAAO,WAAW;AAChB,MAAI,OAAO,WAAW,YACpB;EAEF,MAAM,UAAU,eAAe,GAAG,OAAO,eAAe;AACxD,0BAAwB,SAAS;AACjC,WAAS,QACP,aAAa,cACb,OAAO,sBAAsB,CAC9B;GACD;CAEJ,oBACE,OAAO,WAAW;AAChB,MAAI,OAAO,WAAW,YACpB;EAEF,MAAM,UAAU,eAAe,GAAG,OAAO,eAAe;AACxD,cAAY,cAAc;AAC1B,0BAAwB,SAAS;AACjC,0BAAwB;AACxB,WAAS,QAAQ,aAAa,WAAW,UAAU;AACnD,WAAS,QACP,aAAa,cACb,OAAO,sBAAsB,CAC9B;AACD,WAAS,QACP,aAAa,cACb,OAAO,sBAAsB,CAC9B;GACD;CAEJ,mBAAmB,UAAU,EAAE,KAAK;EAClC,MAAM,mBAAmB;EACzB,MAAM,cAAc,QAAQ,WAAW;EAEvC,MAAM,cAAc,QAAQ,SACxB,OAAO,OAAc,WAAW;GAC9B,MAAM,SAAS,QAAQ;AACvB,OAAI,CAAC,OACH;AAGF,OAAI,OAAO,SAAS;AAClB,WAAO,OAAO,oBAAI,IAAI,MAAM,UAAU,CAAC,CAAC;AACxC;;GAGF,MAAM,gBAAgB,OAAO,OAAO,oBAAI,IAAI,MAAM,UAAU,CAAC,CAAC;AAC9D,UAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,MAAM,CAAC;AACzD,UAAO,OAAO,WAAW;AACvB,WAAO,oBAAoB,SAAS,QAAQ;KAC5C;IACF,GACF,OAAO;EAEX,MAAMC,WAAkC,OAAO,cAC7C,OAAO,IAAI,aAAa;GACtB,MAAM,SAAS,OAAO,kBAAkB;AACxC,OAAI,OAAO,OAAO,OAAO,CACvB,QAAO,OAAO;AAEhB,UAAO,OAAO,MAAM,SAAS,OAAO,iBAAiB,CAAC;AACtD,UAAO,OAAO;IACd,CACH;EAED,MAAM,OAAO,SAAS,KACpB,OAAO,YAAY;GACjB,iCAAiB,IAAI,MAAM,0CAA0C;GACrE,UAAU,SAAS,OAAO,YAAY;GACvC,CAAC,CACH;AAED,SAAO,OAAO,KAAK,MAAM,YAAY;;CAGvC,uBACE,OAAO,YAAY;EACjB;EACA;EACA;EACA,kBAAkB;EAClB,YAAY,wBACR,SAAS,GAAG,wBACZ;EACJ,uBAAuB,wBACnB,SAAS,GAAG,wBACZ;EACL,EAAE;CACN,CAA0B"}
@@ -1,19 +0,0 @@
1
- import { Effect } from "effect";
2
- import { Envelope } from "@interfere/types/sdk/envelope";
3
-
4
- //#region src/effect/layers/storage.layer.d.ts
5
- interface StorageAdapter {
6
- load: () => Effect.Effect<Envelope[]>;
7
- save: (envelopes: Envelope[]) => Effect.Effect<void>;
8
- append: (envelopes: Envelope[]) => Effect.Effect<void>;
9
- removeByIds: (ids: string[]) => Effect.Effect<void>;
10
- dropOldest: (n: number) => Effect.Effect<void>;
11
- clear: () => Effect.Effect<void>;
12
- capacity: () => number;
13
- }
14
- declare function createLocalStorageAdapter(key: string): StorageAdapter;
15
- declare function createIndexedDBAdapter(dbName: string, storeName: string): StorageAdapter;
16
- declare function createMemoryStorageAdapter(): StorageAdapter;
17
- declare function createStorageAdapter(): StorageAdapter;
18
- //#endregion
19
- export { StorageAdapter, createIndexedDBAdapter, createLocalStorageAdapter, createMemoryStorageAdapter, createStorageAdapter };
@@ -1 +0,0 @@
1
- {"version":3,"file":"storage.layer.d.mts","names":[],"sources":["../../../src/effect/layers/storage.layer.ts"],"sourcesContent":[],"mappings":";;;;UAOiB,cAAA;cACH,MAAA,CAAO,OAAO;EADX,IAAA,EAAA,CAAA,SAAA,EAEG,QAFW,EAAA,EAAA,GAEI,MAAA,CAAO,MAFX,CAAA,IAAA,CAAA;EACH,MAAA,EAAA,CAAA,SAAA,EAEN,QAFM,EAAA,EAAA,GAES,MAAA,CAAO,MAFhB,CAAA,IAAA,CAAA;EAAd,WAAO,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,EAAA,GAGa,MAAA,CAAO,MAHpB,CAAA,IAAA,CAAA;EACD,UAAA,EAAA,CAAA,CAAA,EAAA,MAAA,EAAA,GAGS,MAAA,CAAO,MAHhB,CAAA,IAAA,CAAA;EAAe,KAAO,EAAA,GAAA,GAI3B,MAAA,CAAO,MAJoB,CAAA,IAAA,CAAA;EACpB,QAAA,EAAA,GAAA,GAAA,MAAA;;AACY,iBAMlB,yBAAA,CANyB,GAAA,EAAA,MAAA,CAAA,EAMe,cANf;AACZ,iBAmFb,sBAAA,CAnFoB,MAAA,EAAA,MAAA,EAAA,SAAA,EAAA,MAAA,CAAA,EAsFjC,cAtFiC;AACrB,iBA0SC,0BAAA,CAAA,CA1SM,EA0SwB,cA1SxB;AAAM,iBAgVZ,oBAAA,CAAA,CAhVY,EAgVY,cAhVZ"}
@@ -1,200 +0,0 @@
1
- import { name, version } from "../../package.mjs";
2
- import { Effect } from "effect";
3
-
4
- //#region src/effect/layers/storage.layer.ts
5
- function createLocalStorageAdapter(key) {
6
- const capacity = 100;
7
- function loadSync() {
8
- try {
9
- if (typeof localStorage === "undefined") return [];
10
- const raw = localStorage.getItem(key);
11
- if (!raw) return [];
12
- const parsed = JSON.parse(raw);
13
- return Array.isArray(parsed) ? parsed : [];
14
- } catch {
15
- return [];
16
- }
17
- }
18
- function saveSync(list) {
19
- try {
20
- if (typeof localStorage === "undefined") return;
21
- localStorage.setItem(key, JSON.stringify(list));
22
- } catch {}
23
- }
24
- const load = () => Effect.sync(loadSync);
25
- const save = (envelopes) => Effect.sync(() => saveSync(envelopes));
26
- const append = (envelopes) => Effect.sync(() => {
27
- const next = [...loadSync(), ...envelopes];
28
- saveSync(next.length > capacity ? next.slice(next.length - capacity) : next);
29
- });
30
- const removeByIds = (ids) => Effect.sync(() => {
31
- if (ids.length === 0) return;
32
- const set = new Set(ids);
33
- saveSync(loadSync().filter((e) => e.uuid ? !set.has(e.uuid) : true));
34
- });
35
- const dropOldest = (n) => Effect.sync(() => {
36
- const current = loadSync();
37
- saveSync(n >= current.length ? [] : current.slice(n));
38
- });
39
- const clear = () => Effect.sync(() => saveSync([]));
40
- return {
41
- load,
42
- save,
43
- append,
44
- removeByIds,
45
- dropOldest,
46
- clear,
47
- capacity: () => capacity
48
- };
49
- }
50
- function createIndexedDBAdapter(dbName, storeName) {
51
- const capacity = 1e3;
52
- const DB_VERSION = 1;
53
- const openDB = () => Effect.promise(() => new Promise((resolve, reject) => {
54
- if (typeof indexedDB === "undefined") {
55
- reject(/* @__PURE__ */ new Error("IndexedDB not available"));
56
- return;
57
- }
58
- const request = indexedDB.open(dbName, DB_VERSION);
59
- request.onerror = () => reject(request.error);
60
- request.onsuccess = () => resolve(request.result);
61
- request.onupgradeneeded = (event) => {
62
- const db = event.target.result;
63
- if (!db.objectStoreNames.contains(storeName)) db.createObjectStore(storeName, { keyPath: "uuid" }).createIndex("timestamp", "client_ts", { unique: false });
64
- };
65
- }));
66
- const withStore = (mode, operation) => Effect.gen(function* () {
67
- const db = yield* openDB();
68
- try {
69
- const request = operation(db.transaction([storeName], mode).objectStore(storeName));
70
- return yield* Effect.promise(() => new Promise((resolve, reject) => {
71
- request.onsuccess = () => resolve(request.result);
72
- request.onerror = () => reject(request.error);
73
- }));
74
- } finally {
75
- db.close();
76
- }
77
- });
78
- return {
79
- load: () => {
80
- if (typeof indexedDB === "undefined") return Effect.succeed([]);
81
- const eff = withStore("readonly", (store) => store.getAll()).pipe(Effect.map((results) => {
82
- const envelopes = results;
83
- envelopes.sort((a, b) => {
84
- return (a.clientTs || 0) - (b.clientTs || 0);
85
- });
86
- return envelopes.length > capacity ? envelopes.slice(envelopes.length - capacity) : envelopes;
87
- }));
88
- return Effect.sandbox(eff).pipe(Effect.catchAll(() => Effect.succeed([])));
89
- },
90
- save: (envelopes) => Effect.gen(function* () {
91
- const db = yield* openDB();
92
- try {
93
- const tx = db.transaction([storeName], "readwrite");
94
- const store = tx.objectStore(storeName);
95
- yield* Effect.promise(() => new Promise((resolve, reject) => {
96
- const clearReq = store.clear();
97
- clearReq.onsuccess = () => resolve();
98
- clearReq.onerror = () => reject(clearReq.error);
99
- }));
100
- for (const envelope of envelopes) store.add(envelope);
101
- yield* Effect.promise(() => new Promise((resolve, reject) => {
102
- tx.oncomplete = () => resolve();
103
- tx.onerror = () => reject(tx.error);
104
- }));
105
- } finally {
106
- db.close();
107
- }
108
- }).pipe(Effect.catchAll(() => Effect.void)),
109
- append: (envelopes) => Effect.gen(function* () {
110
- const next = [...yield* withStore("readonly", (store) => store.getAll()).pipe(Effect.catchAll(() => Effect.succeed([]))), ...envelopes];
111
- const trimmed = next.length > capacity ? next.slice(next.length - capacity) : next;
112
- yield* Effect.gen(function* () {
113
- const db = yield* openDB();
114
- try {
115
- const tx = db.transaction([storeName], "readwrite");
116
- const store = tx.objectStore(storeName);
117
- store.clear();
118
- for (const env of trimmed) store.add(env);
119
- yield* Effect.promise(() => new Promise((resolve, reject) => {
120
- tx.oncomplete = () => resolve();
121
- tx.onerror = () => reject(tx.error);
122
- }));
123
- } finally {
124
- db.close();
125
- }
126
- }).pipe(Effect.catchAll(() => Effect.void));
127
- }),
128
- removeByIds: (ids) => Effect.gen(function* () {
129
- if (ids.length === 0) return;
130
- const db = yield* openDB();
131
- try {
132
- const tx = db.transaction([storeName], "readwrite");
133
- const store = tx.objectStore(storeName);
134
- for (const id of ids) store.delete(id);
135
- yield* Effect.promise(() => new Promise((resolve, reject) => {
136
- tx.oncomplete = () => resolve();
137
- tx.onerror = () => reject(tx.error);
138
- }));
139
- } finally {
140
- db.close();
141
- }
142
- }).pipe(Effect.catchAll(() => Effect.void)),
143
- dropOldest: (n) => Effect.gen(function* () {
144
- const sorted = (yield* withStore("readonly", (store) => store.getAll())).sort((a, b) => {
145
- return (a.clientTs || 0) - (b.clientTs || 0);
146
- });
147
- const keep = n >= sorted.length ? [] : sorted.slice(n);
148
- const db = yield* openDB();
149
- try {
150
- const tx = db.transaction([storeName], "readwrite");
151
- const store = tx.objectStore(storeName);
152
- store.clear();
153
- for (const env of keep) store.add(env);
154
- yield* Effect.promise(() => new Promise((resolve, reject) => {
155
- tx.oncomplete = () => resolve();
156
- tx.onerror = () => reject(tx.error);
157
- }));
158
- } finally {
159
- db.close();
160
- }
161
- }).pipe(Effect.catchAll(() => Effect.void)),
162
- clear: () => withStore("readwrite", (store) => store.clear()).pipe(Effect.as(void 0), Effect.catchAll(() => Effect.void)),
163
- capacity: () => capacity
164
- };
165
- }
166
- function createMemoryStorageAdapter() {
167
- const capacity = 500;
168
- let buffer = [];
169
- return {
170
- load: () => Effect.succeed(buffer),
171
- save: (envelopes) => Effect.sync(() => {
172
- buffer = envelopes;
173
- }),
174
- append: (envelopes) => Effect.sync(() => {
175
- const next = [...buffer, ...envelopes];
176
- buffer = next.length > capacity ? next.slice(next.length - capacity) : next;
177
- }),
178
- removeByIds: (ids) => Effect.sync(() => {
179
- if (ids.length === 0) return;
180
- const set = new Set(ids);
181
- buffer = buffer.filter((e) => e.uuid ? !set.has(e.uuid) : true);
182
- }),
183
- dropOldest: (n) => Effect.sync(() => {
184
- buffer = n >= buffer.length ? [] : buffer.slice(n);
185
- }),
186
- clear: () => Effect.sync(() => {
187
- buffer = [];
188
- }),
189
- capacity: () => capacity
190
- };
191
- }
192
- function createStorageAdapter() {
193
- const namespace = `${name}:${version}`;
194
- if (typeof indexedDB !== "undefined") return createIndexedDBAdapter(namespace, "envelopes");
195
- if (typeof localStorage !== "undefined") return createLocalStorageAdapter(`${namespace}:envelopes`);
196
- return createMemoryStorageAdapter();
197
- }
198
-
199
- //#endregion
200
- export { createIndexedDBAdapter, createLocalStorageAdapter, createMemoryStorageAdapter, createStorageAdapter };
@@ -1 +0,0 @@
1
- {"version":3,"file":"storage.layer.mjs","names":["buffer: Envelope[]","packageJson.name","packageJson.version"],"sources":["../../../src/effect/layers/storage.layer.ts"],"sourcesContent":["import type { Envelope } from \"@interfere/types/sdk/envelope\";\n\nimport { Effect } from \"effect\";\n\n// Import SDK version for storage namespacing\nimport packageJson from \"../../../package.json\" with { type: \"json\" };\n\nexport interface StorageAdapter {\n load: () => Effect.Effect<Envelope[]>;\n save: (envelopes: Envelope[]) => Effect.Effect<void>;\n append: (envelopes: Envelope[]) => Effect.Effect<void>;\n removeByIds: (ids: string[]) => Effect.Effect<void>;\n dropOldest: (n: number) => Effect.Effect<void>;\n clear: () => Effect.Effect<void>;\n capacity: () => number;\n}\n\nexport function createLocalStorageAdapter(key: string): StorageAdapter {\n const capacity = 100;\n\n function loadSync(): Envelope[] {\n try {\n if (typeof localStorage === \"undefined\") {\n return [];\n }\n const raw = localStorage.getItem(key);\n if (!raw) {\n return [];\n }\n const parsed = JSON.parse(raw);\n return Array.isArray(parsed) ? (parsed as Envelope[]) : [];\n } catch {\n return [];\n }\n }\n\n function saveSync(list: Envelope[]): void {\n try {\n if (typeof localStorage === \"undefined\") {\n return;\n }\n localStorage.setItem(key, JSON.stringify(list));\n } catch {\n // best-effort only\n }\n }\n\n const load = () => Effect.sync(loadSync);\n\n const save = (envelopes: Envelope[]) =>\n Effect.sync(() => saveSync(envelopes));\n\n const append = (envelopes: Envelope[]) =>\n Effect.sync(() => {\n const current = loadSync();\n const next = [...current, ...envelopes];\n const trimmed =\n next.length > capacity ? next.slice(next.length - capacity) : next;\n saveSync(trimmed);\n });\n\n const removeByIds = (ids: string[]) =>\n Effect.sync(() => {\n if (ids.length === 0) {\n return;\n }\n const set = new Set(ids);\n const current = loadSync();\n const filtered = current.filter((e) =>\n e.uuid ? !set.has(e.uuid) : true\n );\n saveSync(filtered);\n });\n\n const dropOldest = (n: number) =>\n Effect.sync(() => {\n const current = loadSync();\n const trimmed = n >= current.length ? [] : current.slice(n);\n saveSync(trimmed);\n });\n\n const clear = () => Effect.sync(() => saveSync([]));\n\n return {\n load,\n save,\n append,\n removeByIds,\n dropOldest,\n clear,\n capacity: () => capacity,\n };\n}\n\n// IndexedDB adapter for larger payloads\nexport function createIndexedDBAdapter(\n dbName: string,\n storeName: string\n): StorageAdapter {\n const capacity = 1000;\n const DB_VERSION = 1;\n\n const openDB = () =>\n Effect.promise(\n () =>\n new Promise<IDBDatabase>((resolve, reject) => {\n if (typeof indexedDB === \"undefined\") {\n reject(new Error(\"IndexedDB not available\"));\n return;\n }\n\n const request = indexedDB.open(dbName, DB_VERSION);\n\n request.onerror = () => reject(request.error);\n request.onsuccess = () => resolve(request.result);\n\n request.onupgradeneeded = (event) => {\n const db = (event.target as IDBOpenDBRequest).result;\n if (!db.objectStoreNames.contains(storeName)) {\n const store = db.createObjectStore(storeName, {\n keyPath: \"uuid\",\n });\n store.createIndex(\"timestamp\", \"client_ts\", { unique: false });\n }\n };\n })\n );\n\n const withStore = <T>(\n mode: IDBTransactionMode,\n operation: (store: IDBObjectStore) => IDBRequest<T>\n ) =>\n Effect.gen(function* () {\n const db = yield* openDB();\n try {\n const tx = db.transaction([storeName], mode);\n const store = tx.objectStore(storeName);\n const request = operation(store);\n\n const result = yield* Effect.promise(\n () =>\n new Promise<T>((resolve, reject) => {\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n })\n );\n\n return result;\n } finally {\n db.close();\n }\n });\n\n return {\n load: () => {\n if (typeof indexedDB === \"undefined\") {\n return Effect.succeed([] as Envelope[]);\n }\n\n const eff = withStore(\"readonly\", (store) => store.getAll()).pipe(\n Effect.map((results) => {\n const envelopes = results as Envelope[];\n // Sort by timestamp and enforce capacity\n envelopes.sort((a, b) => {\n const aTime = a.clientTs || 0;\n const bTime = b.clientTs || 0;\n\n return aTime - bTime;\n });\n\n return envelopes.length > capacity\n ? envelopes.slice(envelopes.length - capacity)\n : envelopes;\n })\n );\n return Effect.sandbox(eff).pipe(\n Effect.catchAll(() => Effect.succeed([] as Envelope[]))\n );\n },\n\n save: (envelopes) =>\n Effect.gen(function* () {\n const db = yield* openDB();\n try {\n const tx = db.transaction([storeName], \"readwrite\");\n const store = tx.objectStore(storeName);\n\n // Clear existing\n yield* Effect.promise(\n () =>\n new Promise<void>((resolve, reject) => {\n const clearReq = store.clear();\n clearReq.onsuccess = () => resolve();\n clearReq.onerror = () => reject(clearReq.error);\n })\n );\n\n for (const envelope of envelopes) {\n store.add(envelope);\n }\n\n yield* Effect.promise(\n () =>\n new Promise<void>((resolve, reject) => {\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n })\n );\n } finally {\n db.close();\n }\n }).pipe(Effect.catchAll(() => Effect.void)),\n\n append: (envelopes) =>\n Effect.gen(function* () {\n const current = (yield* withStore(\"readonly\", (store) =>\n store.getAll()\n ).pipe(\n Effect.catchAll(() => Effect.succeed([] as Envelope[]))\n )) as Envelope[];\n const next = [...current, ...envelopes];\n const trimmed =\n next.length > capacity ? next.slice(next.length - capacity) : next;\n // Reuse save logic to write trimmed set\n yield* Effect.gen(function* () {\n const db = yield* openDB();\n try {\n const tx = db.transaction([storeName], \"readwrite\");\n const store = tx.objectStore(storeName);\n store.clear();\n for (const env of trimmed) {\n store.add(env);\n }\n yield* Effect.promise(\n () =>\n new Promise<void>((resolve, reject) => {\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n })\n );\n } finally {\n db.close();\n }\n }).pipe(Effect.catchAll(() => Effect.void));\n }),\n\n removeByIds: (ids) =>\n Effect.gen(function* () {\n if (ids.length === 0) {\n return;\n }\n const db = yield* openDB();\n try {\n const tx = db.transaction([storeName], \"readwrite\");\n const store = tx.objectStore(storeName);\n for (const id of ids) {\n store.delete(id);\n }\n yield* Effect.promise(\n () =>\n new Promise<void>((resolve, reject) => {\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n })\n );\n } finally {\n db.close();\n }\n }).pipe(Effect.catchAll(() => Effect.void)),\n\n dropOldest: (n) =>\n Effect.gen(function* () {\n const all = yield* withStore(\"readonly\", (store) => store.getAll());\n const sorted = (all as Envelope[]).sort((a, b) => {\n const aTime = a.clientTs || 0;\n const bTime = b.clientTs || 0;\n\n return aTime - bTime;\n });\n const keep = n >= sorted.length ? [] : sorted.slice(n);\n\n const db = yield* openDB();\n try {\n const tx = db.transaction([storeName], \"readwrite\");\n const store = tx.objectStore(storeName);\n store.clear();\n for (const env of keep) {\n store.add(env);\n }\n yield* Effect.promise(\n () =>\n new Promise<void>((resolve, reject) => {\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n })\n );\n } finally {\n db.close();\n }\n }).pipe(Effect.catchAll(() => Effect.void)),\n\n clear: () =>\n withStore(\"readwrite\", (store) => store.clear()).pipe(\n Effect.as(undefined),\n Effect.catchAll(() => Effect.void)\n ),\n capacity: () => capacity,\n };\n}\n\n// In-memory adapter as last-resort fallback\nexport function createMemoryStorageAdapter(): StorageAdapter {\n const capacity = 500;\n\n let buffer: Envelope[] = [];\n\n return {\n load: () => Effect.succeed(buffer),\n save: (envelopes) =>\n Effect.sync(() => {\n buffer = envelopes;\n }),\n append: (envelopes) =>\n Effect.sync(() => {\n const next = [...buffer, ...envelopes];\n buffer =\n next.length > capacity ? next.slice(next.length - capacity) : next;\n }),\n removeByIds: (ids) =>\n Effect.sync(() => {\n if (ids.length === 0) {\n return;\n }\n const set = new Set(ids);\n buffer = buffer.filter((e) => (e.uuid ? !set.has(e.uuid) : true));\n }),\n dropOldest: (n) =>\n Effect.sync(() => {\n buffer = n >= buffer.length ? [] : buffer.slice(n);\n }),\n clear: () =>\n Effect.sync(() => {\n buffer = [];\n }),\n capacity: () => capacity,\n };\n}\n\n// Factory to choose appropriate storage\nexport function createStorageAdapter(): StorageAdapter {\n const sdkName = packageJson.name;\n const sdkVersion = packageJson.version;\n\n const namespace = `${sdkName}:${sdkVersion}`;\n\n // Prefer IndexedDB for all events when available\n if (typeof indexedDB !== \"undefined\") {\n return createIndexedDBAdapter(namespace, \"envelopes\");\n }\n\n if (typeof localStorage !== \"undefined\") {\n return createLocalStorageAdapter(`${namespace}:envelopes`);\n }\n\n // Final fallback: in-memory (lost on refresh)\n return createMemoryStorageAdapter();\n}\n"],"mappings":"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"}
@@ -1,9 +0,0 @@
1
- import { Effect } from "effect";
2
-
3
- //#region src/effect/layers/tracer.layer.d.ts
4
- interface SpanOptions {
5
- attributes?: Record<string, unknown>;
6
- }
7
- declare function withSpan<A, E = never, R = never>(name: string, eff: Effect.Effect<A, E, R>, options?: SpanOptions): Effect.Effect<A, E, R>;
8
- //#endregion
9
- export { SpanOptions, withSpan };
@@ -1 +0,0 @@
1
- {"version":3,"file":"tracer.layer.d.mts","names":[],"sources":["../../../src/effect/layers/tracer.layer.ts"],"sourcesContent":[],"mappings":";;;UAEiB,WAAA;eACF;AADf;AAIgB,iBAAA,QAAQ,CAAA,CAAA,EAAA,IAAA,KAAA,EAAA,IAAA,KAAA,CAAA,CAAA,IAAA,EAAA,MAAA,EAAA,GAAA,EAEjB,MAAA,CAAO,MAFU,CAEH,CAFG,EAEA,CAFA,EAEG,CAFH,CAAA,EAAA,OAAA,CAAA,EAGZ,WAHY,CAAA,EAIrB,MAAA,CAAO,MAJc,CAIP,CAJO,EAIJ,CAJI,EAID,CAJC,CAAA"}
@@ -1,11 +0,0 @@
1
- import { Effect } from "effect";
2
-
3
- //#region src/effect/layers/tracer.layer.ts
4
- function withSpan(name, eff, options) {
5
- const annotated = options?.attributes ? eff.pipe(Effect.annotateLogs(options.attributes)) : eff;
6
- const spanOptions = options?.attributes ? { attributes: options.attributes } : void 0;
7
- return Effect.withSpan(name, spanOptions)(annotated);
8
- }
9
-
10
- //#endregion
11
- export { withSpan };
@@ -1 +0,0 @@
1
- {"version":3,"file":"tracer.layer.mjs","names":[],"sources":["../../../src/effect/layers/tracer.layer.ts"],"sourcesContent":["import { Effect } from \"effect\";\n\nexport interface SpanOptions {\n attributes?: Record<string, unknown>;\n}\n\nexport function withSpan<A, E = never, R = never>(\n name: string,\n eff: Effect.Effect<A, E, R>,\n options?: SpanOptions\n): Effect.Effect<A, E, R> {\n const annotated = options?.attributes\n ? eff.pipe(Effect.annotateLogs(options.attributes))\n : eff;\n\n const spanOptions = options?.attributes\n ? { attributes: options.attributes }\n : undefined;\n\n return Effect.withSpan(name, spanOptions)(annotated);\n}\n"],"mappings":";;;AAMA,SAAgB,SACd,MACA,KACA,SACwB;CACxB,MAAM,YAAY,SAAS,aACvB,IAAI,KAAK,OAAO,aAAa,QAAQ,WAAW,CAAC,GACjD;CAEJ,MAAM,cAAc,SAAS,aACzB,EAAE,YAAY,QAAQ,YAAY,GAClC;AAEJ,QAAO,OAAO,SAAS,MAAM,YAAY,CAAC,UAAU"}
@@ -1,22 +0,0 @@
1
- import { SessionServiceTag } from "./layers/session.layer.mjs";
2
- import { ConfigTag } from "./tags.mjs";
3
- import { ContextServiceTag } from "./layers/context.layer.mjs";
4
- import { HttpServiceTag } from "./layers/http.layer.mjs";
5
- import { QueueServiceTag } from "./layers/queue.layer.mjs";
6
- import { Effect, Layer, Runtime, Scope } from "effect";
7
- import { Config } from "@interfere/types/sdk/config";
8
- import { Layer as Layer$1 } from "effect/Layer";
9
-
10
- //#region src/effect/runtime-services.d.ts
11
- declare const createSDKLayer: (config: Config) => Layer.Layer<QueueServiceTag | SessionServiceTag | ConfigTag | ContextServiceTag | HttpServiceTag, never, never>;
12
- type LayerSuccess<T> = T extends Layer$1<infer ROut, unknown, unknown> ? ROut : never;
13
- type SDKEnv = LayerSuccess<ReturnType<typeof createSDKLayer>>;
14
- declare function setSDKRuntime(scope: Scope.CloseableScope, runtime: Runtime.Runtime<SDKEnv>): void;
15
- declare function initRuntimeServices(input: unknown): void;
16
- declare function runWithSDK<A, E>(effect: Effect.Effect<A, E, SDKEnv>): Promise<A>;
17
- declare function forkWithSDK<E, A>(effect: Effect.Effect<A, E, SDKEnv>): void;
18
- declare function isSDKInitialized(): boolean;
19
- declare function closeSDK(): Promise<void>;
20
- declare function flushQueue(timeoutMs: number): Promise<void>;
21
- //#endregion
22
- export { closeSDK, flushQueue, forkWithSDK, initRuntimeServices, isSDKInitialized, runWithSDK, setSDKRuntime };
@@ -1 +0,0 @@
1
- {"version":3,"file":"runtime-services.d.mts","names":[],"sources":["../../src/effect/runtime-services.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;cAiBM,yBAA0B,WAAM,KAAA,CAAA,MAAA,kBAAA,iBAAA,GAAA,YAAA,iBAAA,GAAA;KAyBjC,kBACH,UAAU;KAEP,MAAA,GAAS,aAAa,kBAAkB;iBAM7B,aAAA,QACP,KAAA,CAAM,yBACJ,OAAA,CAAQ,QAAQ;iBAMX,mBAAA;AA1CV,iBA6FU,UAtEf,CAAA,CAAA,EAAA,CAAA,CAAA,CAAA,MAAA,EAuES,MAAA,CAAO,MAvEhB,CAuEuB,CAvEvB,EAuE0B,CAvE1B,EAuE6B,MAvE7B,CAAA,CAAA,EAwEE,OAxEF,CAwEU,CAxEV,CAAA;AAvB+B,iBAuGhB,WAvGgB,CAAA,CAAA,EAAA,CAAA,CAAA,CAAA,MAAA,EAuGU,MAAA,CAAO,MAvGjB,CAuGwB,CAvGxB,EAuG2B,CAvG3B,EAuG8B,MAvG9B,CAAA,CAAA,EAAA,IAAA;AAAM,iBA2HtB,gBAAA,CAAA,CA3HsB,EAAA,OAAA;AAAA,iBA+HhB,QAAA,CAAA,CA/HgB,EA+HJ,OA/HI,CAAA,IAAA,CAAA;AAAA,iBA0IhB,UAAA,CA1IgB,SAAA,EAAA,MAAA,CAAA,EA0Ie,OA1If,CAAA,IAAA,CAAA"}
@@ -1,76 +0,0 @@
1
- import { getRuntime } from "../core/runtime/config.mjs";
2
- import { SessionServiceLive } from "./layers/session.layer.mjs";
3
- import { ConfigTag } from "./tags.mjs";
4
- import { ContextServiceLive } from "./layers/context.layer.mjs";
5
- import { HttpServiceLive } from "./layers/http.layer.mjs";
6
- import { QueueServiceLive, QueueServiceTag } from "./layers/queue.layer.mjs";
7
- import { Effect, Exit, Layer, Runtime, Scope } from "effect";
8
- import { configSchema } from "@interfere/types/sdk/config";
9
- import { InterfereLogger, withInterfereLogger } from "@interfere/effect-utils/observability";
10
-
11
- //#region src/effect/runtime-services.ts
12
- const createSDKLayer = (config) => {
13
- const configWithRuntime = {
14
- ...config,
15
- runtime: getRuntime()
16
- };
17
- const configLayer = Layer.succeed(ConfigTag, config);
18
- const contextLayer = ContextServiceLive;
19
- const httpLayer = HttpServiceLive(configWithRuntime);
20
- const sessionLayer = SessionServiceLive;
21
- const queueLayer = QueueServiceLive.pipe(Layer.provide(configLayer), Layer.provide(httpLayer));
22
- return Layer.mergeAll(configLayer, contextLayer, httpLayer, sessionLayer, queueLayer);
23
- };
24
- let sdkRuntime = null;
25
- let sdkScope = null;
26
- const shouldEmitConsoleLogs = () => !InterfereLogger.isTestEnvironment();
27
- function setSDKRuntime(scope, runtime) {
28
- sdkScope = scope;
29
- sdkRuntime = runtime;
30
- }
31
- function initRuntimeServices(input) {
32
- if (sdkRuntime) return;
33
- const config = configSchema.parse(input);
34
- if (shouldEmitConsoleLogs()) console.debug("[Interfere SDK] Initializing with config:", config);
35
- (async () => {
36
- const scope = await Effect.runPromise(Scope.make());
37
- const runtime = await Effect.runPromise(Layer.toRuntime(createSDKLayer(config)).pipe(Effect.provideService(Scope.Scope, scope)));
38
- setSDKRuntime(scope, runtime);
39
- if (shouldEmitConsoleLogs()) console.debug("[Interfere SDK] Runtime initialized successfully");
40
- Runtime.runPromise(runtime)(withInterfereLogger("react", Effect.gen(function* () {
41
- yield* (yield* QueueServiceTag).startBatchProcessor().pipe(Effect.provideService(Scope.Scope, scope));
42
- }))).catch((error) => {
43
- Runtime.runPromise(runtime)(withInterfereLogger("react", Effect.logError("Failed to start batch processor", { error: String(error) })));
44
- });
45
- })();
46
- }
47
- function runWithSDK(effect) {
48
- if (!sdkRuntime) throw new Error("SDK not initialized. Call initRuntimeServices first.");
49
- return Runtime.runPromise(sdkRuntime)(withInterfereLogger("react", effect));
50
- }
51
- function forkWithSDK(effect) {
52
- if (!sdkRuntime) {
53
- if (shouldEmitConsoleLogs()) console.warn("[Interfere SDK] Attempted to fork effect before SDK initialized");
54
- return;
55
- }
56
- Runtime.runFork(sdkRuntime)(withInterfereLogger("react", effect).pipe(Effect.catchAllCause((cause) => Effect.logError("Forked effect failed", { cause: String(cause) }))));
57
- }
58
- function isSDKInitialized() {
59
- return sdkRuntime !== null;
60
- }
61
- async function closeSDK() {
62
- if (sdkScope) {
63
- await Effect.runPromise(withInterfereLogger("react", Scope.close(sdkScope, Exit.void)));
64
- sdkScope = null;
65
- sdkRuntime = null;
66
- }
67
- }
68
- async function flushQueue(timeoutMs) {
69
- if (!sdkRuntime) return;
70
- await Runtime.runPromise(sdkRuntime)(Effect.gen(function* () {
71
- yield* (yield* QueueServiceTag).boundedFlush(timeoutMs);
72
- }));
73
- }
74
-
75
- //#endregion
76
- export { closeSDK, flushQueue, forkWithSDK, initRuntimeServices, isSDKInitialized, runWithSDK, setSDKRuntime };
@@ -1 +0,0 @@
1
- {"version":3,"file":"runtime-services.mjs","names":["sdkRuntime: Runtime.Runtime<SDKEnv> | null","sdkScope: Scope.CloseableScope | null"],"sources":["../../src/effect/runtime-services.ts"],"sourcesContent":["import {\n InterfereLogger,\n withInterfereLogger,\n} from \"@interfere/effect-utils/observability\";\nimport type { Config } from \"@interfere/types/sdk/config\";\nimport { configSchema } from \"@interfere/types/sdk/config\";\n\nimport { Effect, Exit, Layer, Runtime, Scope } from \"effect\";\nimport type { Layer as LayerType } from \"effect/Layer\";\n\nimport { getRuntime } from \"../core/runtime/config.js\";\nimport { ContextServiceLive } from \"./layers/context.layer.js\";\nimport { HttpServiceLive } from \"./layers/http.layer.js\";\nimport { QueueServiceLive, QueueServiceTag } from \"./layers/queue.layer.js\";\nimport { SessionServiceLive } from \"./layers/session.layer.js\";\nimport { ConfigTag } from \"./tags.js\";\n\nconst createSDKLayer = (config: Config) => {\n const configWithRuntime = {\n ...config,\n runtime: getRuntime(),\n };\n\n const configLayer = Layer.succeed(ConfigTag, config);\n const contextLayer = ContextServiceLive;\n const httpLayer = HttpServiceLive(configWithRuntime);\n const sessionLayer = SessionServiceLive;\n\n const queueLayer = QueueServiceLive.pipe(\n Layer.provide(configLayer),\n Layer.provide(httpLayer)\n );\n\n return Layer.mergeAll(\n configLayer,\n contextLayer,\n httpLayer,\n sessionLayer,\n queueLayer\n );\n};\n\ntype LayerSuccess<T> =\n T extends LayerType<infer ROut, unknown, unknown> ? ROut : never;\n\ntype SDKEnv = LayerSuccess<ReturnType<typeof createSDKLayer>>;\n\nlet sdkRuntime: Runtime.Runtime<SDKEnv> | null = null;\nlet sdkScope: Scope.CloseableScope | null = null;\nconst shouldEmitConsoleLogs = () => !InterfereLogger.isTestEnvironment();\n\nexport function setSDKRuntime(\n scope: Scope.CloseableScope,\n runtime: Runtime.Runtime<SDKEnv>\n): void {\n sdkScope = scope;\n sdkRuntime = runtime;\n}\n\nexport function initRuntimeServices(input: unknown): void {\n if (sdkRuntime) {\n return;\n }\n\n const config = configSchema.parse(input);\n if (shouldEmitConsoleLogs()) {\n console.debug(\"[Interfere SDK] Initializing with config:\", config);\n }\n\n // Build the runtime asynchronously to avoid synchronous fiber resolution\n // biome-ignore lint/complexity/noVoid: fire-and-forget initialization\n void (async () => {\n const scope = await Effect.runPromise(Scope.make());\n\n const runtime = await Effect.runPromise(\n Layer.toRuntime(createSDKLayer(config)).pipe(\n Effect.provideService(Scope.Scope, scope)\n )\n );\n\n setSDKRuntime(scope, runtime);\n\n if (shouldEmitConsoleLogs()) {\n console.debug(\"[Interfere SDK] Runtime initialized successfully\");\n }\n\n Runtime.runPromise(runtime)(\n withInterfereLogger(\n \"react\",\n Effect.gen(function* () {\n const queue = yield* QueueServiceTag;\n\n yield* queue\n .startBatchProcessor()\n .pipe(Effect.provideService(Scope.Scope, scope));\n })\n )\n ).catch((error) => {\n Runtime.runPromise(runtime)(\n withInterfereLogger(\n \"react\",\n Effect.logError(\"Failed to start batch processor\", {\n error: String(error),\n })\n )\n );\n });\n })();\n}\n\nexport function runWithSDK<A, E>(\n effect: Effect.Effect<A, E, SDKEnv>\n): Promise<A> {\n if (!sdkRuntime) {\n throw new Error(\"SDK not initialized. Call initRuntimeServices first.\");\n }\n\n return Runtime.runPromise(sdkRuntime)(withInterfereLogger(\"react\", effect));\n}\n\nexport function forkWithSDK<E, A>(effect: Effect.Effect<A, E, SDKEnv>): void {\n if (!sdkRuntime) {\n if (shouldEmitConsoleLogs()) {\n console.warn(\n \"[Interfere SDK] Attempted to fork effect before SDK initialized\"\n );\n }\n\n return;\n }\n\n Runtime.runFork(sdkRuntime)(\n withInterfereLogger(\"react\", effect).pipe(\n Effect.catchAllCause((cause) =>\n Effect.logError(\"Forked effect failed\", { cause: String(cause) })\n )\n )\n );\n}\n\nexport function isSDKInitialized(): boolean {\n return sdkRuntime !== null;\n}\n\nexport async function closeSDK(): Promise<void> {\n if (sdkScope) {\n await Effect.runPromise(\n withInterfereLogger(\"react\", Scope.close(sdkScope, Exit.void))\n );\n\n sdkScope = null;\n sdkRuntime = null;\n }\n}\n\nexport async function flushQueue(timeoutMs: number): Promise<void> {\n if (!sdkRuntime) {\n return;\n }\n await Runtime.runPromise(sdkRuntime)(\n Effect.gen(function* () {\n const queue = yield* QueueServiceTag;\n yield* queue.boundedFlush(timeoutMs);\n })\n );\n}\n"],"mappings":";;;;;;;;;;;AAiBA,MAAM,kBAAkB,WAAmB;CACzC,MAAM,oBAAoB;EACxB,GAAG;EACH,SAAS,YAAY;EACtB;CAED,MAAM,cAAc,MAAM,QAAQ,WAAW,OAAO;CACpD,MAAM,eAAe;CACrB,MAAM,YAAY,gBAAgB,kBAAkB;CACpD,MAAM,eAAe;CAErB,MAAM,aAAa,iBAAiB,KAClC,MAAM,QAAQ,YAAY,EAC1B,MAAM,QAAQ,UAAU,CACzB;AAED,QAAO,MAAM,SACX,aACA,cACA,WACA,cACA,WACD;;AAQH,IAAIA,aAA6C;AACjD,IAAIC,WAAwC;AAC5C,MAAM,8BAA8B,CAAC,gBAAgB,mBAAmB;AAExE,SAAgB,cACd,OACA,SACM;AACN,YAAW;AACX,cAAa;;AAGf,SAAgB,oBAAoB,OAAsB;AACxD,KAAI,WACF;CAGF,MAAM,SAAS,aAAa,MAAM,MAAM;AACxC,KAAI,uBAAuB,CACzB,SAAQ,MAAM,6CAA6C,OAAO;AAKpE,EAAM,YAAY;EAChB,MAAM,QAAQ,MAAM,OAAO,WAAW,MAAM,MAAM,CAAC;EAEnD,MAAM,UAAU,MAAM,OAAO,WAC3B,MAAM,UAAU,eAAe,OAAO,CAAC,CAAC,KACtC,OAAO,eAAe,MAAM,OAAO,MAAM,CAC1C,CACF;AAED,gBAAc,OAAO,QAAQ;AAE7B,MAAI,uBAAuB,CACzB,SAAQ,MAAM,mDAAmD;AAGnE,UAAQ,WAAW,QAAQ,CACzB,oBACE,SACA,OAAO,IAAI,aAAa;AAGtB,WAFc,OAAO,iBAGlB,qBAAqB,CACrB,KAAK,OAAO,eAAe,MAAM,OAAO,MAAM,CAAC;IAClD,CACH,CACF,CAAC,OAAO,UAAU;AACjB,WAAQ,WAAW,QAAQ,CACzB,oBACE,SACA,OAAO,SAAS,mCAAmC,EACjD,OAAO,OAAO,MAAM,EACrB,CAAC,CACH,CACF;IACD;KACA;;AAGN,SAAgB,WACd,QACY;AACZ,KAAI,CAAC,WACH,OAAM,IAAI,MAAM,uDAAuD;AAGzE,QAAO,QAAQ,WAAW,WAAW,CAAC,oBAAoB,SAAS,OAAO,CAAC;;AAG7E,SAAgB,YAAkB,QAA2C;AAC3E,KAAI,CAAC,YAAY;AACf,MAAI,uBAAuB,CACzB,SAAQ,KACN,kEACD;AAGH;;AAGF,SAAQ,QAAQ,WAAW,CACzB,oBAAoB,SAAS,OAAO,CAAC,KACnC,OAAO,eAAe,UACpB,OAAO,SAAS,wBAAwB,EAAE,OAAO,OAAO,MAAM,EAAE,CAAC,CAClE,CACF,CACF;;AAGH,SAAgB,mBAA4B;AAC1C,QAAO,eAAe;;AAGxB,eAAsB,WAA0B;AAC9C,KAAI,UAAU;AACZ,QAAM,OAAO,WACX,oBAAoB,SAAS,MAAM,MAAM,UAAU,KAAK,KAAK,CAAC,CAC/D;AAED,aAAW;AACX,eAAa;;;AAIjB,eAAsB,WAAW,WAAkC;AACjE,KAAI,CAAC,WACH;AAEF,OAAM,QAAQ,WAAW,WAAW,CAClC,OAAO,IAAI,aAAa;AAEtB,UADc,OAAO,iBACR,aAAa,UAAU;GACpC,CACH"}
@@ -1,50 +0,0 @@
1
- import { Context } from "effect";
2
-
3
- //#region src/effect/tags.d.ts
4
- declare const ConfigTag_base: Context.TagClass<ConfigTag, "@interfere/react/Config", ({
5
- features: {
6
- errors?: boolean | undefined;
7
- replay?: boolean | undefined;
8
- rageClick?: boolean | undefined;
9
- aiSummary?: boolean | undefined;
10
- pageEvents?: boolean | undefined;
11
- serverTracing?: boolean | undefined;
12
- };
13
- metadata: {
14
- buildId: string | null;
15
- releaseId: string | null;
16
- environment: "development" | "preview" | "production" | null;
17
- runtime: "edge" | "browser" | "node" | null;
18
- };
19
- batch: {
20
- size: number;
21
- ms: number;
22
- };
23
- } & {
24
- proxyUrl: string;
25
- }) | ({
26
- features: {
27
- errors?: boolean | undefined;
28
- replay?: boolean | undefined;
29
- rageClick?: boolean | undefined;
30
- aiSummary?: boolean | undefined;
31
- pageEvents?: boolean | undefined;
32
- serverTracing?: boolean | undefined;
33
- };
34
- metadata: {
35
- buildId: string | null;
36
- releaseId: string | null;
37
- environment: "development" | "preview" | "production" | null;
38
- runtime: "edge" | "browser" | "node" | null;
39
- };
40
- batch: {
41
- size: number;
42
- ms: number;
43
- };
44
- } & {
45
- ingestUrl: string;
46
- surfaceToken: string;
47
- })>;
48
- declare class ConfigTag extends ConfigTag_base {}
49
- //#endregion
50
- export { ConfigTag };
@@ -1 +0,0 @@
1
- {"version":3,"file":"tags.d.mts","names":[],"sources":["../../src/effect/tags.ts"],"sourcesContent":[],"mappings":";;;cAEiC,gBAAA,OAAA,CAAA,SAAA;;IAAA,MAAA,CAAA,EAAA,OAAA,GAAA,SAAA;IAEpB,MAAA,CAAA,EAAU,OAAA,GAAA,SAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAlB,SAAA,SAAkB,cAAA"}