@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,160 @@
1
+ import { createEffectPlugin } from "../plugin-event-system.mjs";
2
+ import { Effect } from "effect";
3
+ import { nanoid } from "nanoid";
4
+
5
+ //#region src/core/plugins/impl/server-tracing.ts
6
+ const X_INTERFERE_REQUEST_HEADER = "x-interfere-request";
7
+ /**
8
+ * Generate a unique request ID
9
+ */
10
+ function generateRequestId() {
11
+ return nanoid();
12
+ }
13
+ /**
14
+ * Check if a URL matches any of the tracing origins
15
+ */
16
+ function shouldTraceUrl(url, tracingOrigins) {
17
+ if (!tracingOrigins) return false;
18
+ if (tracingOrigins === true) try {
19
+ const currentOrigin = window.location.origin;
20
+ return new URL(url, window.location.href).origin === currentOrigin;
21
+ } catch {
22
+ return false;
23
+ }
24
+ for (const pattern of tracingOrigins) if (typeof pattern === "string" && url.includes(pattern) || pattern instanceof RegExp && pattern.test(url)) return true;
25
+ return false;
26
+ }
27
+ /**
28
+ * Get session ID synchronously from localStorage.
29
+ *
30
+ * NOTE: Unlike other plugins that use `ctx.capture()` (which automatically
31
+ * gets session ID via `buildEnvelopeEffect()` -> `SessionServiceTag`),
32
+ * this plugin needs synchronous access because:
33
+ * 1. We're patching network requests (fetch/XHR) synchronously
34
+ * 2. Headers must be set synchronously before requests are sent
35
+ *
36
+ * The session service stores the session ID in localStorage (see session.layer.ts),
37
+ * so reading directly is safe and matches the storage location used by the service.
38
+ */
39
+ function getSessionIdSync() {
40
+ if (typeof window === "undefined") return null;
41
+ try {
42
+ const storage = window.localStorage;
43
+ if (!storage) return null;
44
+ return storage.getItem("__interfere_session_id__");
45
+ } catch {
46
+ return null;
47
+ }
48
+ }
49
+ /**
50
+ * Get session ID asynchronously (for fetch API compatibility).
51
+ * Uses synchronous read since session ID is stored in localStorage.
52
+ */
53
+ function getSessionIdAsync() {
54
+ return Promise.resolve(getSessionIdSync());
55
+ }
56
+ /**
57
+ * Create the x-interfere-request header value
58
+ */
59
+ function createRequestHeader(sessionId, requestId) {
60
+ return `${sessionId ?? ""}/${requestId}`;
61
+ }
62
+ var server_tracing_default = createEffectPlugin("serverTracing", {
63
+ name: "serverTracing",
64
+ setup: (ctx) => Effect.gen(function* () {
65
+ if (typeof window === "undefined") {
66
+ ctx.log.debug("serverTracing: SSR - skipping setup");
67
+ return;
68
+ }
69
+ const tracingOrigins = true;
70
+ ctx.log.debug("serverTracing: patching fetch and XMLHttpRequest", { tracingOrigins });
71
+ const originalFetch = window.fetch.bind(window);
72
+ const extractUrl = (input) => {
73
+ if (typeof input === "string") try {
74
+ return new URL(input, window.location.href).href;
75
+ } catch {
76
+ return input;
77
+ }
78
+ if (input instanceof URL) return input.href;
79
+ try {
80
+ return new URL(input.url, window.location.href).href;
81
+ } catch {
82
+ return input.url;
83
+ }
84
+ };
85
+ const mergeHeaders = (init, request) => {
86
+ const headers = new Headers(init?.headers);
87
+ if (request) {
88
+ for (const [key, value] of request.headers.entries()) if (!headers.has(key)) headers.set(key, value);
89
+ }
90
+ return headers;
91
+ };
92
+ const patchedFetch = async (input, init) => {
93
+ const url = extractUrl(input);
94
+ if (!(url && shouldTraceUrl(url, tracingOrigins))) {
95
+ ctx.log.debug("serverTracing: skipping URL", {
96
+ url,
97
+ tracingOrigins
98
+ });
99
+ return originalFetch(input, init);
100
+ }
101
+ const sessionId = await getSessionIdAsync();
102
+ const requestId = generateRequestId();
103
+ const headerValue = createRequestHeader(sessionId, requestId);
104
+ ctx.log.debug("serverTracing: injecting header", {
105
+ url,
106
+ sessionId,
107
+ requestId,
108
+ headerValue
109
+ });
110
+ const headers = mergeHeaders(init, input instanceof Request ? input : void 0);
111
+ headers.set(X_INTERFERE_REQUEST_HEADER, headerValue);
112
+ if (input instanceof Request) return originalFetch(new Request(input, { headers }));
113
+ return originalFetch(input, {
114
+ ...init,
115
+ headers
116
+ });
117
+ };
118
+ window.fetch = patchedFetch;
119
+ const originalXHROpen = XMLHttpRequest.prototype.open;
120
+ const originalXHRSend = XMLHttpRequest.prototype.send;
121
+ const originalSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
122
+ XMLHttpRequest.prototype.open = function(method, url, ...rest) {
123
+ this._interfereUrl = typeof url === "string" ? url : url.href;
124
+ return originalXHROpen.call(this, method, url, ...rest);
125
+ };
126
+ XMLHttpRequest.prototype.setRequestHeader = function(name, value) {
127
+ const url = this._interfereUrl;
128
+ if (url && shouldTraceUrl(url, tracingOrigins)) {
129
+ const headerValue = createRequestHeader(getSessionIdSync(), generateRequestId());
130
+ if (!this._interfereHeaderSet) {
131
+ originalSetRequestHeader.call(this, X_INTERFERE_REQUEST_HEADER, headerValue);
132
+ this._interfereHeaderSet = true;
133
+ }
134
+ }
135
+ return originalSetRequestHeader.call(this, name, value);
136
+ };
137
+ XMLHttpRequest.prototype.send = function(body) {
138
+ const url = this._interfereUrl;
139
+ if (url && shouldTraceUrl(url, tracingOrigins) && !this._interfereHeaderSet) {
140
+ const headerValue = createRequestHeader(getSessionIdSync(), generateRequestId());
141
+ originalSetRequestHeader.call(this, X_INTERFERE_REQUEST_HEADER, headerValue);
142
+ this._interfereHeaderSet = true;
143
+ }
144
+ return originalXHRSend.call(this, body);
145
+ };
146
+ return {
147
+ key: "serverTracing",
148
+ cleanup: () => {
149
+ ctx.log.debug("serverTracing: removing patches");
150
+ window.fetch = originalFetch;
151
+ XMLHttpRequest.prototype.open = originalXHROpen;
152
+ XMLHttpRequest.prototype.send = originalXHRSend;
153
+ XMLHttpRequest.prototype.setRequestHeader = originalSetRequestHeader;
154
+ }
155
+ };
156
+ })
157
+ });
158
+
159
+ //#endregion
160
+ export { server_tracing_default as default };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-tracing.mjs","names":["originalFetch: typeof window.fetch","patchedFetch: typeof window.fetch"],"sources":["../../../../src/core/plugins/impl/server-tracing.ts"],"sourcesContent":["import { Effect } from \"effect\";\nimport { nanoid } from \"nanoid\";\n\nimport { createEffectPlugin } from \"../plugin-event-system.js\";\n\nconst X_INTERFERE_REQUEST_HEADER = \"x-interfere-request\";\n\n/**\n * Generate a unique request ID\n */\nfunction generateRequestId(): string {\n return nanoid();\n}\n\n/**\n * Check if a URL matches any of the tracing origins\n */\nfunction shouldTraceUrl(\n url: string,\n tracingOrigins?: boolean | (string | RegExp)[]\n): boolean {\n if (!tracingOrigins) {\n return false;\n }\n\n if (tracingOrigins === true) {\n // If true, match all URLs on the same origin\n try {\n const currentOrigin = window.location.origin;\n const urlObj = new URL(url, window.location.href);\n return urlObj.origin === currentOrigin;\n } catch {\n // If URL parsing fails, default to false\n return false;\n }\n }\n\n // Check against array of patterns\n for (const pattern of tracingOrigins) {\n if (\n (typeof pattern === \"string\" && url.includes(pattern)) ||\n (pattern instanceof RegExp && pattern.test(url))\n ) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Get session ID synchronously from localStorage.\n *\n * NOTE: Unlike other plugins that use `ctx.capture()` (which automatically\n * gets session ID via `buildEnvelopeEffect()` -> `SessionServiceTag`),\n * this plugin needs synchronous access because:\n * 1. We're patching network requests (fetch/XHR) synchronously\n * 2. Headers must be set synchronously before requests are sent\n *\n * The session service stores the session ID in localStorage (see session.layer.ts),\n * so reading directly is safe and matches the storage location used by the service.\n */\nfunction getSessionIdSync(): string | null {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n try {\n const storage = window.localStorage;\n if (!storage) {\n return null;\n }\n\n const stored = storage.getItem(\"__interfere_session_id__\");\n return stored;\n } catch {\n // Storage might be blocked or unavailable\n return null;\n }\n}\n\n/**\n * Get session ID asynchronously (for fetch API compatibility).\n * Uses synchronous read since session ID is stored in localStorage.\n */\nfunction getSessionIdAsync(): Promise<string | null> {\n return Promise.resolve(getSessionIdSync());\n}\n\n/**\n * Create the x-interfere-request header value\n */\nfunction createRequestHeader(\n sessionId: string | null,\n requestId: string\n): string {\n // Format: {sessionId}/{requestId}\n // If no session ID yet, use empty string as placeholder\n return `${sessionId ?? \"\"}/${requestId}`;\n}\n\nexport type ServerTracingAPI = null;\n\nexport default createEffectPlugin(\"serverTracing\", {\n name: \"serverTracing\",\n setup: (ctx) =>\n Effect.gen(function* () {\n if (typeof window === \"undefined\") {\n ctx.log.debug(\"serverTracing: SSR - skipping setup\");\n return;\n }\n\n // Default to true - trace all same-origin requests\n // This is plugin-specific config, not part of base SDK config\n const tracingOrigins = true;\n\n ctx.log.debug(\"serverTracing: patching fetch and XMLHttpRequest\", {\n tracingOrigins,\n });\n\n // Patch fetch API\n const originalFetch: typeof window.fetch = window.fetch.bind(window);\n\n const extractUrl = (input: RequestInfo | URL): string => {\n if (typeof input === \"string\") {\n // If it's a relative URL, convert to absolute\n try {\n return new URL(input, window.location.href).href;\n } catch {\n return input;\n }\n }\n if (input instanceof URL) {\n return input.href;\n }\n // Request.url might be relative, convert to absolute\n try {\n return new URL(input.url, window.location.href).href;\n } catch {\n return input.url;\n }\n };\n\n const mergeHeaders = (init?: RequestInit, request?: Request): Headers => {\n const headers = new Headers(init?.headers);\n\n if (request) {\n for (const [key, value] of request.headers.entries()) {\n if (!headers.has(key)) {\n headers.set(key, value);\n }\n }\n }\n\n return headers;\n };\n\n const patchedFetch: typeof window.fetch = async (\n input: RequestInfo | URL,\n init?: RequestInit\n ) => {\n const url = extractUrl(input);\n\n // Check if we should trace this request\n const shouldTrace = url && shouldTraceUrl(url, tracingOrigins);\n if (!shouldTrace) {\n ctx.log.debug(\"serverTracing: skipping URL\", { url, tracingOrigins });\n return originalFetch(input, init);\n }\n\n const sessionId = await getSessionIdAsync();\n const requestId = generateRequestId();\n const headerValue = createRequestHeader(sessionId, requestId);\n\n ctx.log.debug(\"serverTracing: injecting header\", {\n url,\n sessionId,\n requestId,\n headerValue,\n });\n\n // Merge headers\n const headers = mergeHeaders(\n init,\n input instanceof Request ? input : undefined\n );\n\n // Set x-interfere-request header\n headers.set(X_INTERFERE_REQUEST_HEADER, headerValue);\n\n // If input is a Request object, create a new Request\n if (input instanceof Request) {\n return originalFetch(\n new Request(input, {\n headers,\n })\n );\n }\n\n // Create new init object with merged headers\n const newInit: RequestInit = {\n ...init,\n headers,\n };\n\n return originalFetch(input, newInit);\n };\n\n window.fetch = patchedFetch;\n\n // Patch XMLHttpRequest\n // We need to patch setRequestHeader to inject the header when needed\n const originalXHROpen = XMLHttpRequest.prototype.open;\n const originalXHRSend = XMLHttpRequest.prototype.send;\n const originalSetRequestHeader =\n XMLHttpRequest.prototype.setRequestHeader;\n\n XMLHttpRequest.prototype.open = function (\n method: string,\n url: string | URL,\n ...rest: unknown[]\n ) {\n // Store the URL for use later\n const urlString = typeof url === \"string\" ? url : url.href;\n (this as XMLHttpRequest & { _interfereUrl?: string })._interfereUrl =\n urlString;\n\n // Call original - XMLHttpRequest.open accepts 2-5 parameters\n // biome-ignore lint/suspicious/noExplicitAny: XMLHttpRequest.open has variable arity\n return (originalXHROpen as any).call(this, method, url, ...rest);\n };\n\n XMLHttpRequest.prototype.setRequestHeader = function (\n name: string,\n value: string\n ) {\n const url = (this as XMLHttpRequest & { _interfereUrl?: string })\n ._interfereUrl;\n\n // If this is a traced URL, inject our header\n if (url && shouldTraceUrl(url, tracingOrigins)) {\n // Get session ID synchronously for XHR\n const sessionId = getSessionIdSync();\n const requestId = generateRequestId();\n const headerValue = createRequestHeader(sessionId, requestId);\n\n // Set our header first if it hasn't been set\n if (\n !(this as XMLHttpRequest & { _interfereHeaderSet?: boolean })\n ._interfereHeaderSet\n ) {\n originalSetRequestHeader.call(\n this,\n X_INTERFERE_REQUEST_HEADER,\n headerValue\n );\n (\n this as XMLHttpRequest & { _interfereHeaderSet?: boolean }\n )._interfereHeaderSet = true;\n }\n }\n\n return originalSetRequestHeader.call(this, name, value);\n };\n\n XMLHttpRequest.prototype.send = function (\n body?: Document | XMLHttpRequestBodyInit | null\n ) {\n const url = (this as XMLHttpRequest & { _interfereUrl?: string })\n ._interfereUrl;\n\n // Ensure header is set if needed (fallback in case setRequestHeader wasn't called)\n if (\n url &&\n shouldTraceUrl(url, tracingOrigins) &&\n !(this as XMLHttpRequest & { _interfereHeaderSet?: boolean })\n ._interfereHeaderSet\n ) {\n const sessionId = getSessionIdSync();\n const requestId = generateRequestId();\n const headerValue = createRequestHeader(sessionId, requestId);\n originalSetRequestHeader.call(\n this,\n X_INTERFERE_REQUEST_HEADER,\n headerValue\n );\n (\n this as XMLHttpRequest & { _interfereHeaderSet?: boolean }\n )._interfereHeaderSet = true;\n }\n\n return originalXHRSend.call(this, body);\n };\n\n return {\n key: \"serverTracing\",\n cleanup: () => {\n ctx.log.debug(\"serverTracing: removing patches\");\n\n window.fetch = originalFetch;\n XMLHttpRequest.prototype.open = originalXHROpen;\n XMLHttpRequest.prototype.send = originalXHRSend;\n XMLHttpRequest.prototype.setRequestHeader = originalSetRequestHeader;\n },\n };\n }),\n});\n"],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import { AnyEventDefinition, EventDefinitionFor, EventSchemas, EventsForPlugin } from "../events/plugin-event-types.mjs";
2
+ import { Plugin, PluginContext } from "../schemas.mjs";
3
+ import { Effect } from "effect";
4
+ import { PluginKey } from "@interfere/types/sdk/plugins/lib/types";
5
+ import { z } from "zod";
6
+
7
+ //#region src/core/plugins/plugin-event-system.d.ts
8
+ type SetupResult = {
9
+ api?: object;
10
+ cleanup?: () => void;
11
+ } | undefined;
12
+ declare function createPlugin<TKey extends PluginKey>(key: TKey, config: {
13
+ name: string;
14
+ events?: readonly Extract<AnyEventDefinition, {
15
+ type: EventsForPlugin<TKey>;
16
+ }>[];
17
+ setup: (ctx: PluginContext) => SetupResult | Promise<SetupResult>;
18
+ }): Plugin<TKey, unknown>;
19
+ declare function createEffectPlugin<TKey extends PluginKey>(key: TKey, config: {
20
+ name: string;
21
+ events?: readonly Extract<AnyEventDefinition, {
22
+ type: EventsForPlugin<TKey>;
23
+ }>[];
24
+ setup: (ctx: PluginContext) => Effect.Effect<{
25
+ api?: object;
26
+ cleanup?: () => void;
27
+ } | undefined, never>;
28
+ }): Plugin<TKey, unknown>;
29
+ declare function createEffectPlugin<TKey extends PluginKey, TConfig>(key: TKey, config: {
30
+ name: string;
31
+ events?: readonly Extract<AnyEventDefinition, {
32
+ type: EventsForPlugin<TKey>;
33
+ }>[];
34
+ config: TConfig;
35
+ setup: (ctx: PluginContext, config: TConfig) => Effect.Effect<{
36
+ api?: object;
37
+ cleanup?: () => void;
38
+ } | undefined, never>;
39
+ }): Plugin<TKey, unknown>;
40
+ type FinalEventDefinition<T extends keyof EventSchemas> = EventDefinitionFor<T>;
41
+ declare function defineEvent<T extends keyof EventSchemas>(type: T): {
42
+ enrich: (v?: boolean) => EventDefinitionFor<T>;
43
+ transform: <TOut>(fn: (input: z.infer<EventSchemas[T]>) => TOut) => EventDefinitionFor<T>;
44
+ value: () => EventDefinitionFor<T>;
45
+ };
46
+ //#endregion
47
+ export { FinalEventDefinition, createEffectPlugin, createPlugin, defineEvent };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-event-system.d.mts","names":[],"sources":["../../../src/core/plugins/plugin-event-system.ts"],"sourcesContent":[],"mappings":";;;;;;;KAiBK,WAAA;;EAAA,OAAA,CAAA,EAAA,GAAA,GAAW,IAAA;AAOhB,CAAA,GAAgB,SAAA;AAA0B,iBAA1B,YAA0B,CAAA,aAAA,SAAA,CAAA,CAAA,GAAA,EACnC,IADmC,EAAA,MAAA,EAAA;EACnC,IAAA,EAAA,MAAA;EAID,MAAA,CAAA,EAAA,SADgB,OAChB,CAAA,kBAAA,EAAA;IACwB,IAAA,EAAhB,eAAgB,CAAA,IAAA,CAAA;EAAhB,CAAA,CAAA,EAAA;EAFQ,KAAA,EAAA,CAAA,GAAA,EAIL,aAJK,EAAA,GAIa,WAJb,GAI2B,OAJ3B,CAImC,WAJnC,CAAA;CAIL,CAAA,EAEd,MAFc,CAEP,IAFO,EAAA,OAAA,CAAA;AAAkB,iBA8BnB,kBA9BmB,CAAA,aA8Ba,SA9Bb,CAAA,CAAA,GAAA,EA+B5B,IA/B4B,EAAA,MAAA,EAAA;EAAsB,IAAA,EAAA,MAAA;EAAR,MAAA,CAAA,EAAA,SAkC3B,OAlC2B,CAmC3C,kBAnC2C,EAAA;IAEvC,IAAA,EAkCI,eAlCJ,CAkCoB,IAlCpB,CAAA;EAAP,CAAA,CAAA,EAAA;EAAM,KAAA,EAAA,CAAA,GAAA,EAoCQ,aApCR,EAAA,GAoC0B,MAAA,CAAW,MApCrC,CAAA;IA4BO,GAAA,CAAA,EAAA,MAAA;IAAgC,OAAA,CAAA,EAAA,GAAA,GAAA,IAAA;EACzC,CAAA,GAAA,SAAA,EAAA,KAAA,CAAA;CAID,CAAA,EAYH,MAZG,CAYI,IAZJ,EAAA,OAAA,CAAA;AACwB,iBAad,kBAbc,CAAA,aAakB,SAblB,EAAA,OAAA,CAAA,CAAA,GAAA,EAcvB,IAduB,EAAA,MAAA,EAAA;EAAhB,IAAA,EAAA,MAAA;EAFQ,MAAA,CAAA,EAAA,SAmBA,OAnBA,CAoBhB,kBApBgB,EAAA;IAIL,IAAA,EAiBH,eAjBG,CAiBa,IAjBb,CAAA;EAAkB,CAAA,CAAA,EAAW;EASpC,MAAA,EAUE,OAVF;EAAP,KAAA,EAAA,CAAA,GAAA,EAYQ,aAZR,EAAA,MAAA,EAaW,OAbX,EAAA,GAcM,MAAA,CAAW,MAdjB,CAAA;IAAM,GAAA,CAAA,EAAA,MAAA;IAEO,OAAA,CAAA,EAAA,GAAA,GAAA,IAAkB;EAAc,CAAA,GAAA,SAAA,EAAA,KAAA,CAAA;CACzC,CAAA,EAoBJ,MApBI,CAoBG,IApBH,EAAA,OAAA,CAAA;AAID,KA2DM,oBA3DN,CAAA,UAAA,MA2D2C,YA3D3C,CAAA,GA4DJ,kBA5DI,CA4De,CA5Df,CAAA;AACwB,iBA0Fd,WA1Fc,CAAA,UAAA,MA0Fc,YA1Fd,CAAA,CAAA,IAAA,EA0FkC,CA1FlC,CAAA,EAAA;EAAhB,MAAA,EAAA,CAAA,CAAA,CAAA,EAAA,OAAA,EAAA,GA8FU,kBA9FV,CA8FU,CA9FV,CAAA;EAFQ,SAAA,EAAA,CAAA,IAAA,CAAA,CAAA,EAAA,EAAA,CAAA,KAAA,EAiGY,CAAA,CAAE,KAjGd,CAiGoB,YAjGpB,CAiGiC,CAjGjC,CAAA,CAAA,EAAA,GAiGyC,IAjGzC,EAAA,GAiG6C,kBAjG7C,CAiG6C,CAjG7C,CAAA;EAIV,KAAA,EAAA,GAAA,qBAAA,EAAA,CAAA;CAED"}
@@ -0,0 +1,75 @@
1
+ import { eventConfigs, eventSchemas } from "../events/plugin-event-types.mjs";
2
+ import { dynamicRegistry } from "../events/event-registry.mjs";
3
+ import { runWithSDK } from "../../effect/runtime-services.mjs";
4
+
5
+ //#region src/core/plugins/plugin-event-system.ts
6
+ function createPlugin(key, config) {
7
+ return {
8
+ name: config.name,
9
+ events: config.events,
10
+ async setup(ctx) {
11
+ if (config.events) for (const eventDef of config.events) dynamicRegistry.registerDefinition(eventDef);
12
+ const result = await Promise.resolve(config.setup(ctx));
13
+ if (!result) return {
14
+ key,
15
+ api: void 0,
16
+ cleanup: void 0
17
+ };
18
+ return {
19
+ key,
20
+ api: result.api,
21
+ cleanup: result.cleanup
22
+ };
23
+ }
24
+ };
25
+ }
26
+ function createEffectPlugin(key, config) {
27
+ return createPlugin(key, {
28
+ name: config.name,
29
+ events: config.events,
30
+ setup: (ctx) => {
31
+ if ("config" in config && config.config !== void 0) {
32
+ const setupFnWithConfig = config.setup;
33
+ return runWithSDK(setupFnWithConfig(ctx, config.config));
34
+ }
35
+ const setupFnWithoutConfig = config.setup;
36
+ return runWithSDK(setupFnWithoutConfig(ctx));
37
+ }
38
+ });
39
+ }
40
+ var FinalEventDefBuilder = class {
41
+ def;
42
+ constructor(type) {
43
+ this.def = {
44
+ type,
45
+ schema: eventSchemas[type],
46
+ enrich: eventConfigs[type].enrich
47
+ };
48
+ }
49
+ enrich(value = true) {
50
+ return {
51
+ ...this.def,
52
+ enrich: value
53
+ };
54
+ }
55
+ transform(fn) {
56
+ return {
57
+ ...this.def,
58
+ transform: fn
59
+ };
60
+ }
61
+ value() {
62
+ return { ...this.def };
63
+ }
64
+ };
65
+ function defineEvent(type) {
66
+ const builder = new FinalEventDefBuilder(type);
67
+ return {
68
+ enrich: (v) => builder.enrich(v ?? true),
69
+ transform: (fn) => builder.transform(fn),
70
+ value: () => builder.value()
71
+ };
72
+ }
73
+
74
+ //#endregion
75
+ export { createEffectPlugin, createPlugin, defineEvent };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-event-system.mjs","names":[],"sources":["../../../src/core/plugins/plugin-event-system.ts"],"sourcesContent":["import type { PluginKey } from \"@interfere/types/sdk/plugins/lib/types\";\n\nimport type { Effect as EffectType } from \"effect\";\nimport type { z } from \"zod\";\n\nimport { runWithSDK } from \"../../effect/runtime-services.js\";\nimport { dynamicRegistry } from \"../events/event-registry.js\";\nimport {\n type AnyEventDefinition,\n type EventDefinitionFor,\n type EventSchemas,\n type EventsForPlugin,\n eventConfigs,\n eventSchemas,\n} from \"../events/plugin-event-types.js\";\nimport type { Plugin, PluginContext } from \"../schemas.js\";\n\ntype SetupResult =\n | {\n api?: object;\n cleanup?: () => void;\n }\n | undefined;\n\nexport function createPlugin<TKey extends PluginKey>(\n key: TKey,\n config: {\n name: string;\n events?: readonly Extract<\n AnyEventDefinition,\n { type: EventsForPlugin<TKey> }\n >[];\n setup: (ctx: PluginContext) => SetupResult | Promise<SetupResult>;\n }\n): Plugin<TKey, unknown> {\n return {\n name: config.name,\n events: config.events,\n async setup(ctx: PluginContext) {\n // Register event handlers if provided\n if (config.events) {\n for (const eventDef of config.events) {\n dynamicRegistry.registerDefinition(eventDef);\n }\n }\n\n // Run the plugin's setup\n const result = await Promise.resolve(config.setup(ctx));\n\n if (!result) {\n return { key, api: undefined, cleanup: undefined };\n }\n\n return {\n key,\n api: result.api,\n cleanup: result.cleanup,\n };\n },\n };\n}\n\nexport function createEffectPlugin<TKey extends PluginKey>(\n key: TKey,\n config: {\n name: string;\n events?: readonly Extract<\n AnyEventDefinition,\n { type: EventsForPlugin<TKey> }\n >[];\n setup: (ctx: PluginContext) => EffectType.Effect<\n | {\n api?: object;\n cleanup?: () => void;\n }\n | undefined,\n never\n >;\n }\n): Plugin<TKey, unknown>;\n\nexport function createEffectPlugin<TKey extends PluginKey, TConfig>(\n key: TKey,\n config: {\n name: string;\n events?: readonly Extract<\n AnyEventDefinition,\n { type: EventsForPlugin<TKey> }\n >[];\n config: TConfig;\n setup: (\n ctx: PluginContext,\n config: TConfig\n ) => EffectType.Effect<\n | {\n api?: object;\n cleanup?: () => void;\n }\n | undefined,\n never\n >;\n }\n): Plugin<TKey, unknown>;\n\nexport function createEffectPlugin<TKey extends PluginKey, TConfig = undefined>(\n key: TKey,\n config: {\n name: string;\n events?: readonly Extract<\n AnyEventDefinition,\n { type: EventsForPlugin<TKey> }\n >[];\n config?: TConfig;\n setup: (\n ctx: PluginContext,\n config?: TConfig\n ) => EffectType.Effect<\n | {\n api?: object;\n cleanup?: () => void;\n }\n | undefined,\n never\n >;\n }\n): Plugin<TKey, unknown> {\n return createPlugin(key, {\n name: config.name,\n events: config.events,\n setup: (ctx) => {\n if (\"config\" in config && config.config !== undefined) {\n const setupFnWithConfig = config.setup as (\n context: PluginContext,\n cfg: TConfig\n ) => EffectType.Effect<SetupResult, never>;\n return runWithSDK(setupFnWithConfig(ctx, config.config));\n }\n const setupFnWithoutConfig = config.setup as (\n context: PluginContext\n ) => EffectType.Effect<SetupResult, never>;\n return runWithSDK(setupFnWithoutConfig(ctx));\n },\n });\n}\n\nexport type FinalEventDefinition<T extends keyof EventSchemas> =\n EventDefinitionFor<T>;\n\nclass FinalEventDefBuilder<T extends keyof EventSchemas> {\n private readonly def: FinalEventDefinition<T>;\n\n constructor(type: T) {\n this.def = {\n type,\n schema: eventSchemas[type],\n enrich: eventConfigs[type].enrich,\n } as FinalEventDefinition<T>;\n }\n\n enrich(value = true): FinalEventDefinition<T> {\n return { ...this.def, enrich: value } as FinalEventDefinition<T>;\n }\n\n transform<TOut>(\n fn: (input: z.infer<EventSchemas[T]>) => TOut\n ): FinalEventDefinition<T> {\n return {\n ...this.def,\n transform: fn as (i: unknown) => unknown,\n } as FinalEventDefinition<T>;\n }\n\n value(): FinalEventDefinition<T> {\n return { ...this.def } as FinalEventDefinition<T>;\n }\n}\n\nexport function defineEvent<T extends keyof EventSchemas>(type: T) {\n const builder = new FinalEventDefBuilder(type);\n\n return {\n enrich: (v?: boolean) => builder.enrich(v ?? true),\n transform: <TOut>(fn: (input: z.infer<EventSchemas[T]>) => TOut) =>\n builder.transform(fn),\n value: () => builder.value(),\n };\n}\n"],"mappings":";;;;;AAwBA,SAAgB,aACd,KACA,QAQuB;AACvB,QAAO;EACL,MAAM,OAAO;EACb,QAAQ,OAAO;EACf,MAAM,MAAM,KAAoB;AAE9B,OAAI,OAAO,OACT,MAAK,MAAM,YAAY,OAAO,OAC5B,iBAAgB,mBAAmB,SAAS;GAKhD,MAAM,SAAS,MAAM,QAAQ,QAAQ,OAAO,MAAM,IAAI,CAAC;AAEvD,OAAI,CAAC,OACH,QAAO;IAAE;IAAK,KAAK;IAAW,SAAS;IAAW;AAGpD,UAAO;IACL;IACA,KAAK,OAAO;IACZ,SAAS,OAAO;IACjB;;EAEJ;;AA6CH,SAAgB,mBACd,KACA,QAmBuB;AACvB,QAAO,aAAa,KAAK;EACvB,MAAM,OAAO;EACb,QAAQ,OAAO;EACf,QAAQ,QAAQ;AACd,OAAI,YAAY,UAAU,OAAO,WAAW,QAAW;IACrD,MAAM,oBAAoB,OAAO;AAIjC,WAAO,WAAW,kBAAkB,KAAK,OAAO,OAAO,CAAC;;GAE1D,MAAM,uBAAuB,OAAO;AAGpC,UAAO,WAAW,qBAAqB,IAAI,CAAC;;EAE/C,CAAC;;AAMJ,IAAM,uBAAN,MAAyD;CACvD,AAAiB;CAEjB,YAAY,MAAS;AACnB,OAAK,MAAM;GACT;GACA,QAAQ,aAAa;GACrB,QAAQ,aAAa,MAAM;GAC5B;;CAGH,OAAO,QAAQ,MAA+B;AAC5C,SAAO;GAAE,GAAG,KAAK;GAAK,QAAQ;GAAO;;CAGvC,UACE,IACyB;AACzB,SAAO;GACL,GAAG,KAAK;GACR,WAAW;GACZ;;CAGH,QAAiC;AAC/B,SAAO,EAAE,GAAG,KAAK,KAAK;;;AAI1B,SAAgB,YAA0C,MAAS;CACjE,MAAM,UAAU,IAAI,qBAAqB,KAAK;AAE9C,QAAO;EACL,SAAS,MAAgB,QAAQ,OAAO,KAAK,KAAK;EAClD,YAAkB,OAChB,QAAQ,UAAU,GAAG;EACvB,aAAa,QAAQ,OAAO;EAC7B"}
@@ -0,0 +1,22 @@
1
+ import { InferredApis, KnownPluginApis, Plugin, PluginContext } from "../schemas.mjs";
2
+ import { Effect } from "effect";
3
+ import { Config } from "@interfere/types/sdk/config";
4
+ import { PluginKey } from "@interfere/types/sdk/plugins/lib/types";
5
+
6
+ //#region src/core/plugins/plugin-loader.d.ts
7
+ type PluginCleanup = () => void;
8
+ interface PluginLoader {
9
+ loadAndSetupPlugins<P extends readonly Plugin<string, unknown>[] | undefined>(config: Config, pluginContext: PluginContext, userPlugins?: P): Promise<{
10
+ cleanups: PluginCleanup[];
11
+ apis: Partial<KnownPluginApis & (P extends undefined ? Record<never, never> : InferredApis<NonNullable<P>>)>;
12
+ keys: Set<PluginKey | (P extends undefined ? never : InferredPluginKey<P>)>;
13
+ }>;
14
+ }
15
+ type InferredPluginKey<P> = P extends readonly Plugin<string, unknown>[] ? P[number] extends Plugin<infer K, unknown> ? K : never : never;
16
+ declare function loadAndSetupPluginsEffect<P extends readonly Plugin<string, unknown>[] | undefined>(config: Config, pluginContext: PluginContext, userPlugins?: P): Effect.Effect<{
17
+ cleanups: PluginCleanup[];
18
+ apis: Readonly<Partial<KnownPluginApis & (P extends undefined ? Record<never, never> : InferredApis<NonNullable<P>>)>>;
19
+ keys: Set<PluginKey | (P extends undefined ? never : InferredPluginKey<P>)>;
20
+ }, never, never>;
21
+ //#endregion
22
+ export { PluginCleanup, PluginLoader, loadAndSetupPluginsEffect };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-loader.d.mts","names":[],"sources":["../../../src/core/plugins/plugin-loader.ts"],"sourcesContent":[],"mappings":";;;;;;KAkBY,aAAA;UAEK,YAAA;EAFL,mBAAa,CAAA,UAAA,SAGgB,MAHhB,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,GAAA,SAAA,CAAA,CAAA,MAAA,EAIb,MAJa,EAAA,aAAA,EAKN,aALM,EAAA,WAAA,CAAA,EAMP,CANO,CAAA,EAOpB,OAPoB,CAAA;IAER,QAAA,EAMH,aANe,EAAA;IACY,IAAA,EAM/B,OAN+B,CAOnC,eAPmC,GAAA,CAQhC,CARgC,SAAA,SAAA,GAS7B,MAT6B,CAAA,KAAA,EAAA,KAAA,CAAA,GAU7B,YAV6B,CAUhB,WAVgB,CAUJ,CAVI,CAAA,CAAA,CAAA,CAAA;IAC7B,IAAA,EAWF,GAXE,CAWE,SAXF,GAAA,CAWe,CAXf,SAAA,SAAA,GAAA,KAAA,GAW6C,iBAX7C,CAW+D,CAX/D,CAAA,CAAA,CAAA;EACO,CAAA,CAAA;;KAcd,iBAXS,CAAA,CAAA,CAAA,GAWc,CAXd,SAAA,SAWiC,MAXjC,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,GAYV,CAZU,CAAA,MAAA,CAAA,SAYQ,MAZR,CAAA,KAAA,EAAA,EAAA,OAAA,CAAA,GAAA,CAAA,GAAA,KAAA,GAAA,KAAA;AAER,iBAoBU,yBApBV,CAAA,UAAA,SAqBe,MArBf,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,GAAA,SAAA,CAAA,CAAA,MAAA,EAsBI,MAtBJ,EAAA,aAAA,EAsB2B,aAtB3B,EAAA,WAAA,CAAA,EAsBwD,CAtBxD,CAAA,EAsByD,MAAA,CAAA,MAtBzD,CAAA;EACG,QAAA,eAAA,EAAA;EACG,IAAA,UAAA,QAAA,gBAAA,GAAA,EAAA,SAAA,SAAA,SAAA,CAAA,KAAA,EAAA,KAAA,CAAA,eAAA,YAAA,EAAA,CAAA,CAAA,CAAA,CAAA,CAAA;EACyB,IAAA,EAmQjB,GAnQiB,CAoQ7B,SApQ6B,GAAA,CAoQhB,CApQgB,SAAA,SAAA,GAAA,KAAA,GAoQc,iBApQd,CAoQgC,CApQhC,CAAA,CAAA,CAAA;CAAZ,EAAA,KAAA,EAAA,KAAA,CAAA"}
@@ -0,0 +1,142 @@
1
+ import { dynamicRegistry } from "../events/event-registry.mjs";
2
+ import { withSpan } from "../../effect/layers/tracer.layer.mjs";
3
+ import { Effect } from "effect";
4
+ import { PLUGIN_MANIFEST } from "@interfere/types/sdk/plugins/manifest";
5
+
6
+ //#region src/core/plugins/plugin-loader.ts
7
+ function loadAndSetupPluginsEffect(config, pluginContext, userPlugins) {
8
+ const handlers = [];
9
+ const apis = {};
10
+ const keys = /* @__PURE__ */ new Set();
11
+ const registerPluginEvents = (plugin) => Effect.gen(function* () {
12
+ const withEvents = plugin;
13
+ if (withEvents.events && withEvents.events.length > 0) {
14
+ yield* Effect.logTrace(`Registering ${withEvents.events.length} events for plugin '${plugin.name}'`).pipe(Effect.annotateLogs({
15
+ plugin: plugin.name,
16
+ eventCount: withEvents.events.length
17
+ }));
18
+ for (const eventDef of withEvents.events) dynamicRegistry.registerDefinition(eventDef);
19
+ }
20
+ });
21
+ const registerExposeKey = (expose) => Effect.gen(function* () {
22
+ if (expose.key && isPluginKey(expose.key)) {
23
+ keys.add(expose.key);
24
+ yield* Effect.logTrace(`Plugin '${expose.key}' registered`).pipe(Effect.annotateLogs({ expose }));
25
+ }
26
+ });
27
+ const registerExposeCleanup = (expose) => Effect.gen(function* () {
28
+ if (typeof expose.cleanup === "function") {
29
+ handlers.push(expose.cleanup);
30
+ yield* Effect.logTrace(`Plugin '${expose.key}' registered expose cleanup`).pipe(Effect.annotateLogs({ expose }));
31
+ }
32
+ });
33
+ const registerExposeApi = (expose) => Effect.gen(function* () {
34
+ if (expose.api && expose.key) {
35
+ apis[expose.key] = expose.api;
36
+ yield* Effect.logTrace(`Plugin '${expose.key}' exposed API`).pipe(Effect.annotateLogs({
37
+ key: expose.key,
38
+ api: expose.api
39
+ }));
40
+ }
41
+ });
42
+ const processSetupResult = (result) => Effect.gen(function* () {
43
+ if (!result) {
44
+ yield* Effect.logTrace("Plugin returned no expose (skipped)");
45
+ return;
46
+ }
47
+ if (typeof result === "function") {
48
+ handlers.push(result);
49
+ yield* Effect.logTrace(`Registered cleanup handler - ${handlers.length} total`).pipe(Effect.annotateLogs({ result }));
50
+ return;
51
+ }
52
+ yield* registerExposeKey(result);
53
+ yield* registerExposeCleanup(result);
54
+ yield* registerExposeApi(result);
55
+ });
56
+ const setupPlugin = (plugin) => Effect.gen(function* () {
57
+ try {
58
+ yield* Effect.logTrace(`Setting up plugin '${plugin.name}'`).pipe(Effect.annotateLogs({ plugin: plugin.name }));
59
+ yield* registerPluginEvents(plugin);
60
+ yield* processSetupResult(yield* withSpan("plugin.setup", Effect.promise(() => Promise.resolve(plugin.setup(pluginContext))), { attributes: { pluginName: plugin.name } }));
61
+ yield* Effect.logTrace(`Plugin '${plugin.name}' setup complete`).pipe(Effect.annotateLogs({ plugin: plugin.name }));
62
+ } catch (error) {
63
+ yield* Effect.logError("Failed to setup plugin").pipe(Effect.annotateLogs({
64
+ plugin: plugin.name,
65
+ error: error instanceof Error ? error.message : String(error)
66
+ }));
67
+ }
68
+ });
69
+ const loadPluginModule = (key) => {
70
+ switch (key) {
71
+ case "errors": return import("./impl/errors.mjs");
72
+ case "replay": return import("./impl/replay.mjs");
73
+ case "rageClick": return import("./impl/rage-click.mjs");
74
+ case "aiSummary": return import("./impl/ai-summary.mjs");
75
+ case "pageEvents": return import("./impl/page-events.mjs");
76
+ case "serverTracing": return import("./impl/server-tracing.mjs");
77
+ default: return Promise.reject(/* @__PURE__ */ new Error(`Unknown plugin key: ${key}`));
78
+ }
79
+ };
80
+ const isPluginKey = (key) => typeof key === "string" && PLUGIN_MANIFEST.some(({ name }) => name === key);
81
+ const createLoadPluginEffect = (key) => Effect.gen(function* () {
82
+ try {
83
+ yield* Effect.logTrace("Importing plugin module").pipe(Effect.annotateLogs({ key }));
84
+ const mod = yield* Effect.promise(() => loadPluginModule(key));
85
+ yield* Effect.logTrace("Imported plugin module").pipe(Effect.annotateLogs({ key }));
86
+ const plugin = mod.default;
87
+ if (plugin && typeof plugin === "object") yield* setupPlugin(plugin);
88
+ else yield* Effect.logError("Plugin missing default export").pipe(Effect.annotateLogs({ key }));
89
+ } catch (error) {
90
+ yield* Effect.logError("Failed to import plugin").pipe(Effect.annotateLogs({
91
+ key,
92
+ error: String(error)
93
+ }));
94
+ }
95
+ });
96
+ const loadBuiltinPlugins = Effect.gen(function* () {
97
+ const loadPromises = [];
98
+ const entries = Object.entries(config.features);
99
+ const enabled = entries.filter(([_, v]) => v).map(([k]) => k);
100
+ const disabled = entries.filter(([_, v]) => !v).map(([k]) => k);
101
+ yield* Effect.logDebug(`Loading ${enabled.length} plugins (${disabled.length ?? "Nothing"} disabled)`).pipe(Effect.annotateLogs({
102
+ total: entries.length,
103
+ enabled,
104
+ disabled
105
+ }));
106
+ for (const [key, value] of entries) {
107
+ if (!value) {
108
+ yield* Effect.logTrace(`Plugin '${key}' disabled`).pipe(Effect.annotateLogs({ key }));
109
+ continue;
110
+ }
111
+ if (!isPluginKey(key)) {
112
+ yield* Effect.logError("Invalid plugin key", { key });
113
+ continue;
114
+ }
115
+ const loadPlugin = createLoadPluginEffect(key);
116
+ loadPromises.push(loadPlugin);
117
+ }
118
+ yield* Effect.all(loadPromises, { concurrency: "unbounded" });
119
+ });
120
+ const loadUserPlugins = Effect.gen(function* () {
121
+ if (userPlugins) {
122
+ const setupPromises = userPlugins.map((plugin) => setupPlugin(plugin));
123
+ yield* Effect.all(setupPromises, { concurrency: "unbounded" });
124
+ }
125
+ });
126
+ const warnIfNoPluginsLoaded = Effect.gen(function* () {
127
+ if (Object.keys(apis).length === 0) yield* Effect.logWarning("No plugins were loaded. Check your config.features to enable plugins.");
128
+ });
129
+ return Effect.gen(function* () {
130
+ yield* Effect.logTrace("Starting plugin loading process").pipe(Effect.annotateLogs({ config }));
131
+ yield* Effect.all([loadBuiltinPlugins, loadUserPlugins], { concurrency: "unbounded" });
132
+ yield* warnIfNoPluginsLoaded;
133
+ return {
134
+ cleanups: handlers,
135
+ apis: Object.freeze({ ...apis }),
136
+ keys
137
+ };
138
+ });
139
+ }
140
+
141
+ //#endregion
142
+ export { loadAndSetupPluginsEffect };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-loader.mjs","names":["handlers: PluginCleanup[]","apis: Apis<P>","loadPromises: Effect.Effect<void, never, never>[]"],"sources":["../../../src/core/plugins/plugin-loader.ts"],"sourcesContent":["import type { Config } from \"@interfere/types/sdk/config\";\nimport type { PluginKey } from \"@interfere/types/sdk/plugins/lib/types\";\nimport { PLUGIN_MANIFEST } from \"@interfere/types/sdk/plugins/manifest\";\n\nimport { Effect } from \"effect\";\n\nimport { withSpan } from \"../../effect/layers/tracer.layer.js\";\nimport { dynamicRegistry } from \"../events/event-registry.js\";\nimport type { AnyEventDefinition } from \"../events/plugin-event-types.js\";\nimport type {\n InferredApis,\n KnownPluginApis,\n Plugin,\n PluginContext,\n PluginExpose,\n} from \"../schemas.js\";\n// Unified Plugin type; enhanced variants removed\n\nexport type PluginCleanup = () => void;\n\nexport interface PluginLoader {\n loadAndSetupPlugins<P extends readonly Plugin<string, unknown>[] | undefined>(\n config: Config,\n pluginContext: PluginContext,\n userPlugins?: P\n ): Promise<{\n cleanups: PluginCleanup[];\n apis: Partial<\n KnownPluginApis &\n (P extends undefined\n ? Record<never, never>\n : InferredApis<NonNullable<P>>)\n >;\n keys: Set<PluginKey | (P extends undefined ? never : InferredPluginKey<P>)>;\n }>;\n}\n\ntype InferredPluginKey<P> = P extends readonly Plugin<string, unknown>[]\n ? P[number] extends Plugin<infer K, unknown>\n ? K\n : never\n : never;\n\ntype Apis<P extends readonly Plugin<string, unknown>[] | undefined> = Partial<\n KnownPluginApis &\n (P extends undefined ? Record<never, never> : InferredApis<NonNullable<P>>)\n>;\n\nexport function loadAndSetupPluginsEffect<\n P extends readonly Plugin<string, unknown>[] | undefined,\n>(config: Config, pluginContext: PluginContext, userPlugins?: P) {\n const handlers: PluginCleanup[] = [];\n const apis: Apis<P> = {};\n\n const keys = new Set<\n PluginKey | (P extends undefined ? never : InferredPluginKey<P>)\n >();\n\n // Register event handlers declared on the plugin\n const registerPluginEvents = (plugin: Plugin) =>\n Effect.gen(function* () {\n const withEvents = plugin as { events?: readonly AnyEventDefinition[] };\n\n if (withEvents.events && withEvents.events.length > 0) {\n yield* Effect.logTrace(\n `Registering ${withEvents.events.length} events for plugin '${plugin.name}'`\n ).pipe(\n Effect.annotateLogs({\n plugin: plugin.name,\n eventCount: withEvents.events.length,\n })\n );\n\n for (const eventDef of withEvents.events) {\n dynamicRegistry.registerDefinition(eventDef);\n }\n }\n });\n\n // Helpers to keep processSetupResult complexity low\n const registerExposeKey = (expose: PluginExpose<string, unknown>) =>\n Effect.gen(function* () {\n if (expose.key && isPluginKey(expose.key)) {\n keys.add(expose.key);\n\n yield* Effect.logTrace(`Plugin '${expose.key}' registered`).pipe(\n Effect.annotateLogs({ expose })\n );\n }\n });\n\n const registerExposeCleanup = (expose: PluginExpose<string, unknown>) =>\n Effect.gen(function* () {\n if (typeof expose.cleanup === \"function\") {\n handlers.push(expose.cleanup);\n\n yield* Effect.logTrace(\n `Plugin '${expose.key}' registered expose cleanup`\n ).pipe(Effect.annotateLogs({ expose }));\n }\n });\n\n const registerExposeApi = (expose: PluginExpose<string, unknown>) =>\n Effect.gen(function* () {\n if (expose.api && expose.key) {\n (apis as Record<string, unknown>)[expose.key] = expose.api;\n\n yield* Effect.logTrace(`Plugin '${expose.key}' exposed API`).pipe(\n Effect.annotateLogs({ key: expose.key, api: expose.api })\n );\n }\n });\n\n const processSetupResult = (\n result: PluginExpose<string, unknown> | (() => void) | undefined\n ) =>\n Effect.gen(function* () {\n if (!result) {\n yield* Effect.logTrace(\"Plugin returned no expose (skipped)\");\n return;\n }\n\n if (typeof result === \"function\") {\n handlers.push(result);\n\n yield* Effect.logTrace(\n `Registered cleanup handler - ${handlers.length} total`\n ).pipe(Effect.annotateLogs({ result }));\n\n return;\n }\n\n yield* registerExposeKey(result);\n yield* registerExposeCleanup(result);\n yield* registerExposeApi(result);\n });\n\n const setupPlugin = (plugin: Plugin) =>\n Effect.gen(function* () {\n try {\n yield* Effect.logTrace(`Setting up plugin '${plugin.name}'`).pipe(\n Effect.annotateLogs({ plugin: plugin.name })\n );\n\n yield* registerPluginEvents(plugin);\n\n const result = yield* withSpan(\n \"plugin.setup\",\n Effect.promise(() => Promise.resolve(plugin.setup(pluginContext))),\n { attributes: { pluginName: plugin.name } }\n );\n\n yield* processSetupResult(result);\n\n yield* Effect.logTrace(`Plugin '${plugin.name}' setup complete`).pipe(\n Effect.annotateLogs({ plugin: plugin.name })\n );\n } catch (error) {\n yield* Effect.logError(\"Failed to setup plugin\").pipe(\n Effect.annotateLogs({\n plugin: plugin.name,\n error: error instanceof Error ? error.message : String(error),\n })\n );\n }\n });\n\n // Helper to load a plugin module - all plugins export Plugin objects directly\n // TODO: Replace with a dynamic import\n const loadPluginModule = (key: PluginKey): Promise<{ default: Plugin }> => {\n switch (key) {\n case \"errors\":\n return import(\"./impl/errors.js\");\n case \"replay\":\n return import(\"./impl/replay.js\");\n case \"rageClick\":\n return import(\"./impl/rage-click.js\");\n case \"aiSummary\":\n return import(\"./impl/ai-summary.js\");\n case \"pageEvents\":\n return import(\"./impl/page-events.js\");\n case \"serverTracing\":\n return import(\"./impl/server-tracing.js\");\n default:\n return Promise.reject(new Error(`Unknown plugin key: ${key}`));\n }\n };\n\n // Check if a value is a valid plugin key\n const isPluginKey = (key: unknown): key is PluginKey =>\n typeof key === \"string\" && PLUGIN_MANIFEST.some(({ name }) => name === key);\n\n const createLoadPluginEffect = (key: PluginKey) =>\n Effect.gen(function* () {\n try {\n yield* Effect.logTrace(\"Importing plugin module\").pipe(\n Effect.annotateLogs({ key })\n );\n\n const mod = yield* Effect.promise(() => loadPluginModule(key));\n\n yield* Effect.logTrace(\"Imported plugin module\").pipe(\n Effect.annotateLogs({ key })\n );\n\n const plugin = mod.default;\n\n if (plugin && typeof plugin === \"object\") {\n yield* setupPlugin(plugin);\n } else {\n yield* Effect.logError(\"Plugin missing default export\").pipe(\n Effect.annotateLogs({ key })\n );\n }\n } catch (error) {\n yield* Effect.logError(\"Failed to import plugin\").pipe(\n Effect.annotateLogs({ key, error: String(error) })\n );\n }\n });\n\n // Load built-in plugins based on config\n const loadBuiltinPlugins = Effect.gen(function* () {\n const loadPromises: Effect.Effect<void, never, never>[] = [];\n\n const entries = Object.entries(config.features);\n const enabled = entries.filter(([_, v]) => v).map(([k]) => k);\n const disabled = entries.filter(([_, v]) => !v).map(([k]) => k);\n\n yield* Effect.logDebug(\n `Loading ${enabled.length} plugins (${disabled.length ?? \"Nothing\"} disabled)`\n ).pipe(Effect.annotateLogs({ total: entries.length, enabled, disabled }));\n\n for (const [key, value] of entries) {\n if (!value) {\n yield* Effect.logTrace(`Plugin '${key}' disabled`).pipe(\n Effect.annotateLogs({ key })\n );\n\n continue;\n }\n\n if (!isPluginKey(key)) {\n yield* Effect.logError(\"Invalid plugin key\", {\n key,\n });\n\n continue;\n }\n\n const loadPlugin = createLoadPluginEffect(key);\n\n loadPromises.push(loadPlugin);\n }\n\n // Run all plugin loads in parallel\n yield* Effect.all(loadPromises, { concurrency: \"unbounded\" });\n });\n\n // Load user-provided plugins\n const loadUserPlugins = Effect.gen(function* () {\n if (userPlugins) {\n const setupPromises = userPlugins.map((plugin) => setupPlugin(plugin));\n yield* Effect.all(setupPromises, { concurrency: \"unbounded\" });\n }\n });\n\n const warnIfNoPluginsLoaded = Effect.gen(function* () {\n if (Object.keys(apis).length === 0) {\n yield* Effect.logWarning(\n \"No plugins were loaded. Check your config.features to enable plugins.\"\n );\n }\n });\n\n // Run everything: load first (in parallel), then warn if nothing loaded\n return Effect.gen(function* () {\n yield* Effect.logTrace(\"Starting plugin loading process\").pipe(\n Effect.annotateLogs({ config })\n );\n\n yield* Effect.all([loadBuiltinPlugins, loadUserPlugins], {\n concurrency: \"unbounded\",\n });\n\n yield* warnIfNoPluginsLoaded;\n\n return {\n cleanups: handlers,\n apis: Object.freeze({ ...apis }),\n keys: keys as Set<\n PluginKey | (P extends undefined ? never : InferredPluginKey<P>)\n >,\n };\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { Config } from "@interfere/types/sdk/config";
2
+ import { Runtime } from "@interfere/types/sdk/runtime";
3
+
4
+ //#region src/core/runtime/config.d.ts
5
+ declare function getRuntime(): Runtime;
6
+ declare function initConfig(input: unknown): void;
7
+ declare function getConfig(): Config;
8
+ interface IngestTarget {
9
+ url: string;
10
+ headers: Headers;
11
+ }
12
+ declare function resolveIngestTarget(): IngestTarget;
13
+ //#endregion
14
+ export { IngestTarget, getConfig, getRuntime, initConfig, resolveIngestTarget };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.mts","names":[],"sources":["../../../src/core/runtime/config.ts"],"sourcesContent":[],"mappings":";;;;iBAKgB,UAAA,CAAA,GAAc;iBAkBd,UAAA;AAlBA,iBAwBA,SAAA,CAAA,CAxBc,EAwBD,MAxBQ;AAkBrB,UAcC,YAAA,CAdS;EAMV,GAAA,EAAA,MAAA;EAQC,OAAA,EAEN,OAFkB;AAK7B;iBAAgB,mBAAA,CAAA,GAAuB"}
@@ -0,0 +1,39 @@
1
+ import { configSchema } from "@interfere/types/sdk/config";
2
+
3
+ //#region src/core/runtime/config.ts
4
+ let currentConfig;
5
+ function getRuntime() {
6
+ if (typeof window !== "undefined") return "browser";
7
+ try {
8
+ if (process.env.NEXT_RUNTIME === "edge") return "edge";
9
+ return "node";
10
+ } catch (error) {
11
+ console.error("Error getting runtime: ", error);
12
+ return null;
13
+ }
14
+ }
15
+ function initConfig(input) {
16
+ currentConfig = {
17
+ ...configSchema.parse(input),
18
+ runtime: getRuntime()
19
+ };
20
+ }
21
+ function getConfig() {
22
+ if (!currentConfig) throw new Error("Config not initialized");
23
+ return currentConfig;
24
+ }
25
+ function resolveIngestTarget() {
26
+ const cfg = getConfig();
27
+ if ("proxyUrl" in cfg) return {
28
+ url: cfg.proxyUrl,
29
+ headers: new Headers([["Content-Type", "application/json"]])
30
+ };
31
+ if ("ingestUrl" in cfg && "surfaceToken" in cfg) return {
32
+ url: cfg.ingestUrl,
33
+ headers: new Headers([["Content-Type", "application/json"], ["x-interfere-surface", cfg.surfaceToken]])
34
+ };
35
+ throw new Error("Invalid SDK config: must provide proxyUrl or (ingestUrl + surfaceToken)");
36
+ }
37
+
38
+ //#endregion
39
+ export { getConfig, getRuntime, initConfig, resolveIngestTarget };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.mjs","names":["currentConfig: (Config & { runtime: Runtime }) | undefined"],"sources":["../../../src/core/runtime/config.ts"],"sourcesContent":["import { type Config, configSchema } from \"@interfere/types/sdk/config\";\nimport type { Runtime } from \"@interfere/types/sdk/runtime\";\n\nlet currentConfig: (Config & { runtime: Runtime }) | undefined;\n\nexport function getRuntime(): Runtime {\n if (typeof window !== \"undefined\") {\n return \"browser\";\n }\n\n try {\n if (process.env.NEXT_RUNTIME === \"edge\") {\n return \"edge\";\n }\n\n return \"node\";\n } catch (error) {\n console.error(\"Error getting runtime: \", error);\n\n return null;\n }\n}\n\nexport function initConfig(input: unknown) {\n const parsed = configSchema.parse(input);\n\n currentConfig = { ...parsed, runtime: getRuntime() };\n}\n\nexport function getConfig(): Config {\n if (!currentConfig) {\n throw new Error(\"Config not initialized\");\n }\n\n return currentConfig;\n}\n\nexport interface IngestTarget {\n url: string;\n headers: Headers;\n}\n\nexport function resolveIngestTarget(): IngestTarget {\n const cfg = getConfig();\n\n if (\"proxyUrl\" in cfg) {\n return {\n url: cfg.proxyUrl,\n headers: new Headers([[\"Content-Type\", \"application/json\"]]),\n };\n }\n\n if (\"ingestUrl\" in cfg && \"surfaceToken\" in cfg) {\n return {\n url: cfg.ingestUrl,\n headers: new Headers([\n [\"Content-Type\", \"application/json\"],\n [\"x-interfere-surface\", cfg.surfaceToken],\n ]),\n };\n }\n\n throw new Error(\n \"Invalid SDK config: must provide proxyUrl or (ingestUrl + surfaceToken)\"\n );\n}\n"],"mappings":";;;AAGA,IAAIA;AAEJ,SAAgB,aAAsB;AACpC,KAAI,OAAO,WAAW,YACpB,QAAO;AAGT,KAAI;AACF,MAAI,QAAQ,IAAI,iBAAiB,OAC/B,QAAO;AAGT,SAAO;UACA,OAAO;AACd,UAAQ,MAAM,2BAA2B,MAAM;AAE/C,SAAO;;;AAIX,SAAgB,WAAW,OAAgB;AAGzC,iBAAgB;EAAE,GAFH,aAAa,MAAM,MAAM;EAEX,SAAS,YAAY;EAAE;;AAGtD,SAAgB,YAAoB;AAClC,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,yBAAyB;AAG3C,QAAO;;AAQT,SAAgB,sBAAoC;CAClD,MAAM,MAAM,WAAW;AAEvB,KAAI,cAAc,IAChB,QAAO;EACL,KAAK,IAAI;EACT,SAAS,IAAI,QAAQ,CAAC,CAAC,gBAAgB,mBAAmB,CAAC,CAAC;EAC7D;AAGH,KAAI,eAAe,OAAO,kBAAkB,IAC1C,QAAO;EACL,KAAK,IAAI;EACT,SAAS,IAAI,QAAQ,CACnB,CAAC,gBAAgB,mBAAmB,EACpC,CAAC,uBAAuB,IAAI,aAAa,CAC1C,CAAC;EACH;AAGH,OAAM,IAAI,MACR,0EACD"}
@@ -0,0 +1,25 @@
1
+ import { Effect } from "effect";
2
+ import { IResult } from "@ua-parser-js/pro-enterprise";
3
+
4
+ //#region src/core/runtime/context.d.ts
5
+ interface ScreenProperties {
6
+ viewport: {
7
+ viewport_width: number;
8
+ viewport_height: number;
9
+ };
10
+ screen: {
11
+ screen_height: number;
12
+ screen_width: number;
13
+ };
14
+ }
15
+ interface CaptureSourceProperties {
16
+ sdk: {
17
+ name: string;
18
+ version: string;
19
+ language: string;
20
+ };
21
+ }
22
+ type ContextProperties = ScreenProperties & CaptureSourceProperties & IResult & Record<string, unknown>;
23
+ declare function getContextProperties(): Effect.Effect<ContextProperties>;
24
+ //#endregion
25
+ export { ContextProperties, getContextProperties };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.mts","names":[],"sources":["../../../src/core/runtime/context.ts"],"sourcesContent":[],"mappings":";;;;UAKU,gBAAA;;IAAA,cAAA,EAAgB,MAAA;IAWhB,eAAA,EAAA,MAAuB;EAQrB,CAAA;EAAoB,MAAA,EAAA;IAC9B,aAAA,EAAA,MAAA;IACA,YAAA,EAAA,MAAA;EACA,CAAA;;AAEF,UAbU,uBAAA,CAa0B;;;;;;;KALxB,iBAAA,GAAoB,mBAC9B,0BACA,UACA;iBAEc,oBAAA,CAAA,GAAwB,MAAA,CAAO,OAAO"}