@interfere/react 0.1.0-alpha.5 → 0.2.0-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 (210) hide show
  1. package/README.md +90 -0
  2. package/dist/error-boundary.d.mts +27 -0
  3. package/dist/error-boundary.d.mts.map +1 -0
  4. package/dist/error-boundary.mjs +42 -0
  5. package/dist/error-boundary.mjs.map +1 -0
  6. package/dist/internal/client.d.mts +13 -0
  7. package/dist/internal/client.d.mts.map +1 -0
  8. package/dist/internal/client.mjs +80 -0
  9. package/dist/internal/client.mjs.map +1 -0
  10. package/dist/internal/config.d.mts +9 -0
  11. package/dist/internal/config.d.mts.map +1 -0
  12. package/dist/internal/config.mjs +27 -0
  13. package/dist/internal/config.mjs.map +1 -0
  14. package/dist/internal/context.d.mts +6 -0
  15. package/dist/internal/context.d.mts.map +1 -0
  16. package/dist/internal/context.mjs +32 -0
  17. package/dist/internal/context.mjs.map +1 -0
  18. package/dist/internal/envelope.d.mts +14 -0
  19. package/dist/internal/envelope.d.mts.map +1 -0
  20. package/dist/internal/envelope.mjs +20 -0
  21. package/dist/internal/envelope.mjs.map +1 -0
  22. package/dist/internal/errors.d.mts +4 -0
  23. package/dist/internal/errors.d.mts.map +1 -0
  24. package/dist/internal/errors.mjs +4 -0
  25. package/dist/internal/errors.mjs.map +1 -0
  26. package/dist/internal/sw.d.mts +4 -0
  27. package/dist/internal/sw.d.mts.map +1 -0
  28. package/dist/internal/sw.mjs +10 -0
  29. package/dist/internal/sw.mjs.map +1 -0
  30. package/dist/plugins/errors.d.mts +6 -0
  31. package/dist/plugins/errors.d.mts.map +1 -0
  32. package/dist/plugins/errors.mjs +59 -0
  33. package/dist/plugins/errors.mjs.map +1 -0
  34. package/dist/plugins/lib/loader.d.mts +9 -0
  35. package/dist/plugins/lib/loader.d.mts.map +1 -0
  36. package/dist/plugins/lib/loader.mjs +47 -0
  37. package/dist/plugins/lib/loader.mjs.map +1 -0
  38. package/dist/plugins/lib/types.d.mts +14 -0
  39. package/dist/plugins/lib/types.d.mts.map +1 -0
  40. package/dist/plugins/lib/types.mjs +1 -0
  41. package/dist/plugins/pages.d.mts +6 -0
  42. package/dist/plugins/pages.d.mts.map +1 -0
  43. package/dist/plugins/pages.mjs +102 -0
  44. package/dist/plugins/pages.mjs.map +1 -0
  45. package/dist/plugins/rage-clicks.d.mts +6 -0
  46. package/dist/plugins/rage-clicks.d.mts.map +1 -0
  47. package/dist/plugins/rage-clicks.mjs +53 -0
  48. package/dist/plugins/rage-clicks.mjs.map +1 -0
  49. package/dist/plugins/replay.d.mts +6 -0
  50. package/dist/plugins/replay.d.mts.map +1 -0
  51. package/dist/plugins/replay.mjs +62 -0
  52. package/dist/plugins/replay.mjs.map +1 -0
  53. package/dist/provider.d.mts +17 -11
  54. package/dist/provider.d.mts.map +1 -1
  55. package/dist/provider.mjs +18 -17
  56. package/dist/provider.mjs.map +1 -1
  57. package/dist/tracking/api.d.mts +22 -0
  58. package/dist/tracking/api.d.mts.map +1 -0
  59. package/dist/tracking/api.mjs +88 -0
  60. package/dist/tracking/api.mjs.map +1 -0
  61. package/dist/tracking/session.d.mts +19 -0
  62. package/dist/tracking/session.d.mts.map +1 -0
  63. package/dist/tracking/session.mjs +92 -0
  64. package/dist/tracking/session.mjs.map +1 -0
  65. package/dist/tracking/visitor.d.mts +6 -0
  66. package/dist/tracking/visitor.d.mts.map +1 -0
  67. package/dist/tracking/visitor.mjs +35 -0
  68. package/dist/tracking/visitor.mjs.map +1 -0
  69. package/dist/transport/http.d.mts +15 -0
  70. package/dist/transport/http.d.mts.map +1 -0
  71. package/dist/transport/http.mjs +56 -0
  72. package/dist/transport/http.mjs.map +1 -0
  73. package/dist/transport/queue.d.mts +25 -0
  74. package/dist/transport/queue.d.mts.map +1 -0
  75. package/dist/transport/queue.mjs +60 -0
  76. package/dist/transport/queue.mjs.map +1 -0
  77. package/dist/util/log.d.mts +13 -0
  78. package/dist/util/log.d.mts.map +1 -0
  79. package/dist/util/log.mjs +37 -0
  80. package/dist/util/log.mjs.map +1 -0
  81. package/package.json +43 -66
  82. package/dist/client.d.mts +0 -15
  83. package/dist/client.d.mts.map +0 -1
  84. package/dist/client.mjs +0 -75
  85. package/dist/client.mjs.map +0 -1
  86. package/dist/core/events/event-registry.d.mts +0 -23
  87. package/dist/core/events/event-registry.d.mts.map +0 -1
  88. package/dist/core/events/event-registry.mjs +0 -32
  89. package/dist/core/events/event-registry.mjs.map +0 -1
  90. package/dist/core/events/plugin-event-types.d.mts +0 -92
  91. package/dist/core/events/plugin-event-types.d.mts.map +0 -1
  92. package/dist/core/events/plugin-event-types.mjs +0 -25
  93. package/dist/core/events/plugin-event-types.mjs.map +0 -1
  94. package/dist/core/plugins/dom-utils.d.mts +0 -9
  95. package/dist/core/plugins/dom-utils.d.mts.map +0 -1
  96. package/dist/core/plugins/dom-utils.mjs +0 -25
  97. package/dist/core/plugins/dom-utils.mjs.map +0 -1
  98. package/dist/core/plugins/impl/ai-summary.d.mts +0 -6
  99. package/dist/core/plugins/impl/ai-summary.d.mts.map +0 -1
  100. package/dist/core/plugins/impl/ai-summary.mjs +0 -122
  101. package/dist/core/plugins/impl/ai-summary.mjs.map +0 -1
  102. package/dist/core/plugins/impl/errors.d.mts +0 -9
  103. package/dist/core/plugins/impl/errors.d.mts.map +0 -1
  104. package/dist/core/plugins/impl/errors.mjs +0 -160
  105. package/dist/core/plugins/impl/errors.mjs.map +0 -1
  106. package/dist/core/plugins/impl/page-events.d.mts +0 -15
  107. package/dist/core/plugins/impl/page-events.d.mts.map +0 -1
  108. package/dist/core/plugins/impl/page-events.mjs +0 -131
  109. package/dist/core/plugins/impl/page-events.mjs.map +0 -1
  110. package/dist/core/plugins/impl/rage-click.d.mts +0 -6
  111. package/dist/core/plugins/impl/rage-click.d.mts.map +0 -1
  112. package/dist/core/plugins/impl/rage-click.mjs +0 -53
  113. package/dist/core/plugins/impl/rage-click.mjs.map +0 -1
  114. package/dist/core/plugins/impl/replay.d.mts +0 -9
  115. package/dist/core/plugins/impl/replay.d.mts.map +0 -1
  116. package/dist/core/plugins/impl/replay.mjs +0 -144
  117. package/dist/core/plugins/impl/replay.mjs.map +0 -1
  118. package/dist/core/plugins/impl/server-tracing.d.mts +0 -7
  119. package/dist/core/plugins/impl/server-tracing.d.mts.map +0 -1
  120. package/dist/core/plugins/impl/server-tracing.mjs +0 -160
  121. package/dist/core/plugins/impl/server-tracing.mjs.map +0 -1
  122. package/dist/core/plugins/plugin-event-system.d.mts +0 -47
  123. package/dist/core/plugins/plugin-event-system.d.mts.map +0 -1
  124. package/dist/core/plugins/plugin-event-system.mjs +0 -75
  125. package/dist/core/plugins/plugin-event-system.mjs.map +0 -1
  126. package/dist/core/plugins/plugin-loader.d.mts +0 -22
  127. package/dist/core/plugins/plugin-loader.d.mts.map +0 -1
  128. package/dist/core/plugins/plugin-loader.mjs +0 -142
  129. package/dist/core/plugins/plugin-loader.mjs.map +0 -1
  130. package/dist/core/runtime/config.d.mts +0 -14
  131. package/dist/core/runtime/config.d.mts.map +0 -1
  132. package/dist/core/runtime/config.mjs +0 -39
  133. package/dist/core/runtime/config.mjs.map +0 -1
  134. package/dist/core/runtime/context.d.mts +0 -25
  135. package/dist/core/runtime/context.d.mts.map +0 -1
  136. package/dist/core/runtime/context.mjs +0 -48
  137. package/dist/core/runtime/context.mjs.map +0 -1
  138. package/dist/core/runtime/ingest-target.d.mts +0 -10
  139. package/dist/core/runtime/ingest-target.d.mts.map +0 -1
  140. package/dist/core/runtime/ingest-target.mjs +0 -15
  141. package/dist/core/runtime/ingest-target.mjs.map +0 -1
  142. package/dist/core/runtime/native-fetch.d.mts +0 -32
  143. package/dist/core/runtime/native-fetch.d.mts.map +0 -1
  144. package/dist/core/runtime/native-fetch.mjs +0 -49
  145. package/dist/core/runtime/native-fetch.mjs.map +0 -1
  146. package/dist/core/schemas.d.mts +0 -85
  147. package/dist/core/schemas.d.mts.map +0 -1
  148. package/dist/core/schemas.mjs +0 -1
  149. package/dist/effect/build-envelope.d.mts +0 -9
  150. package/dist/effect/build-envelope.d.mts.map +0 -1
  151. package/dist/effect/build-envelope.mjs +0 -29
  152. package/dist/effect/build-envelope.mjs.map +0 -1
  153. package/dist/effect/errors.d.mts +0 -36
  154. package/dist/effect/errors.d.mts.map +0 -1
  155. package/dist/effect/errors.mjs +0 -10
  156. package/dist/effect/errors.mjs.map +0 -1
  157. package/dist/effect/layers/config.layer.d.mts +0 -13
  158. package/dist/effect/layers/config.layer.d.mts.map +0 -1
  159. package/dist/effect/layers/config.layer.mjs +0 -21
  160. package/dist/effect/layers/config.layer.mjs.map +0 -1
  161. package/dist/effect/layers/context.layer.d.mts +0 -12
  162. package/dist/effect/layers/context.layer.d.mts.map +0 -1
  163. package/dist/effect/layers/context.layer.mjs +0 -14
  164. package/dist/effect/layers/context.layer.mjs.map +0 -1
  165. package/dist/effect/layers/http.layer.d.mts +0 -21
  166. package/dist/effect/layers/http.layer.d.mts.map +0 -1
  167. package/dist/effect/layers/http.layer.mjs +0 -114
  168. package/dist/effect/layers/http.layer.mjs.map +0 -1
  169. package/dist/effect/layers/queue.layer.d.mts +0 -30
  170. package/dist/effect/layers/queue.layer.d.mts.map +0 -1
  171. package/dist/effect/layers/queue.layer.mjs +0 -258
  172. package/dist/effect/layers/queue.layer.mjs.map +0 -1
  173. package/dist/effect/layers/session.layer.d.mts +0 -26
  174. package/dist/effect/layers/session.layer.d.mts.map +0 -1
  175. package/dist/effect/layers/session.layer.mjs +0 -126
  176. package/dist/effect/layers/session.layer.mjs.map +0 -1
  177. package/dist/effect/layers/storage.layer.d.mts +0 -50
  178. package/dist/effect/layers/storage.layer.d.mts.map +0 -1
  179. package/dist/effect/layers/storage.layer.mjs +0 -180
  180. package/dist/effect/layers/storage.layer.mjs.map +0 -1
  181. package/dist/effect/layers/tracer.layer.d.mts +0 -9
  182. package/dist/effect/layers/tracer.layer.d.mts.map +0 -1
  183. package/dist/effect/layers/tracer.layer.mjs +0 -11
  184. package/dist/effect/layers/tracer.layer.mjs.map +0 -1
  185. package/dist/effect/runtime-services.d.mts +0 -22
  186. package/dist/effect/runtime-services.d.mts.map +0 -1
  187. package/dist/effect/runtime-services.mjs +0 -76
  188. package/dist/effect/runtime-services.mjs.map +0 -1
  189. package/dist/effect/tags.d.mts +0 -58
  190. package/dist/effect/tags.d.mts.map +0 -1
  191. package/dist/effect/tags.mjs +0 -7
  192. package/dist/effect/tags.mjs.map +0 -1
  193. package/dist/hooks/use-runtime-and-plugins.d.mts +0 -7
  194. package/dist/hooks/use-runtime-and-plugins.d.mts.map +0 -1
  195. package/dist/hooks/use-runtime-and-plugins.mjs +0 -153
  196. package/dist/hooks/use-runtime-and-plugins.mjs.map +0 -1
  197. package/dist/hooks/use-session.d.mts +0 -40
  198. package/dist/hooks/use-session.d.mts.map +0 -1
  199. package/dist/hooks/use-session.mjs +0 -96
  200. package/dist/hooks/use-session.mjs.map +0 -1
  201. package/dist/package.mjs +0 -100
  202. package/dist/package.mjs.map +0 -1
  203. package/dist/server/auth.d.mts +0 -11
  204. package/dist/server/auth.d.mts.map +0 -1
  205. package/dist/server/auth.mjs +0 -36
  206. package/dist/server/auth.mjs.map +0 -1
  207. package/dist/server/capture.d.mts +0 -18
  208. package/dist/server/capture.d.mts.map +0 -1
  209. package/dist/server/capture.mjs +0 -105
  210. package/dist/server/capture.mjs.map +0 -1
@@ -1,180 +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 createIndexedDBAdapter(dbName, storeName, maxQueueSize = 1e3) {
6
- const capacity = maxQueueSize;
7
- const DB_VERSION = 1;
8
- const openDB = () => Effect.promise(() => new Promise((resolve, reject) => {
9
- if (typeof indexedDB === "undefined") {
10
- reject(/* @__PURE__ */ new Error("IndexedDB not available"));
11
- return;
12
- }
13
- const request = indexedDB.open(dbName, DB_VERSION);
14
- request.onerror = () => reject(request.error);
15
- request.onsuccess = () => resolve(request.result);
16
- request.onupgradeneeded = (event) => {
17
- const db = event.target.result;
18
- if (!db.objectStoreNames.contains(storeName)) db.createObjectStore(storeName, { keyPath: "uuid" }).createIndex("timestamp", "client_ts", { unique: false });
19
- };
20
- }));
21
- const withStore = (mode, operation) => Effect.gen(function* () {
22
- const db = yield* openDB();
23
- try {
24
- const request = operation(db.transaction([storeName], mode).objectStore(storeName));
25
- return yield* Effect.promise(() => new Promise((resolve, reject) => {
26
- request.onsuccess = () => resolve(request.result);
27
- request.onerror = () => reject(request.error);
28
- }));
29
- } finally {
30
- db.close();
31
- }
32
- });
33
- return {
34
- load: () => {
35
- if (typeof indexedDB === "undefined") return Effect.succeed([]);
36
- const eff = withStore("readonly", (store) => store.getAll()).pipe(Effect.map((results) => {
37
- const envelopes = results;
38
- envelopes.sort((a, b) => {
39
- return (a.clientTs || 0) - (b.clientTs || 0);
40
- });
41
- return envelopes.length > capacity ? envelopes.slice(envelopes.length - capacity) : envelopes;
42
- }));
43
- return Effect.sandbox(eff).pipe(Effect.catchAll(() => Effect.succeed([])));
44
- },
45
- save: (envelopes) => Effect.gen(function* () {
46
- const db = yield* openDB();
47
- try {
48
- const tx = db.transaction([storeName], "readwrite");
49
- const store = tx.objectStore(storeName);
50
- yield* Effect.promise(() => new Promise((resolve, reject) => {
51
- const clearReq = store.clear();
52
- clearReq.onsuccess = () => resolve();
53
- clearReq.onerror = () => reject(clearReq.error);
54
- }));
55
- for (const envelope of envelopes) store.add(envelope);
56
- yield* Effect.promise(() => new Promise((resolve, reject) => {
57
- tx.oncomplete = () => resolve();
58
- tx.onerror = () => reject(tx.error);
59
- }));
60
- } finally {
61
- db.close();
62
- }
63
- }).pipe(Effect.catchAll(() => Effect.void)),
64
- append: (envelopes) => Effect.gen(function* () {
65
- const next = [...yield* withStore("readonly", (store) => store.getAll()).pipe(Effect.catchAll(() => Effect.succeed([]))), ...envelopes];
66
- const trimmed = next.length > capacity ? next.slice(next.length - capacity) : next;
67
- yield* Effect.gen(function* () {
68
- const db = yield* openDB();
69
- try {
70
- const tx = db.transaction([storeName], "readwrite");
71
- const store = tx.objectStore(storeName);
72
- store.clear();
73
- for (const env of trimmed) store.add(env);
74
- yield* Effect.promise(() => new Promise((resolve, reject) => {
75
- tx.oncomplete = () => resolve();
76
- tx.onerror = () => reject(tx.error);
77
- }));
78
- } finally {
79
- db.close();
80
- }
81
- }).pipe(Effect.catchAll(() => Effect.void));
82
- }),
83
- removeByIds: (ids) => Effect.gen(function* () {
84
- if (ids.length === 0) return;
85
- const db = yield* openDB();
86
- try {
87
- const tx = db.transaction([storeName], "readwrite");
88
- const store = tx.objectStore(storeName);
89
- for (const id of ids) store.delete(id);
90
- yield* Effect.promise(() => new Promise((resolve, reject) => {
91
- tx.oncomplete = () => resolve();
92
- tx.onerror = () => reject(tx.error);
93
- }));
94
- } finally {
95
- db.close();
96
- }
97
- }).pipe(Effect.catchAll(() => Effect.void)),
98
- dropOldest: (n) => Effect.gen(function* () {
99
- const sorted = (yield* withStore("readonly", (store) => store.getAll())).sort((a, b) => {
100
- return (a.clientTs || 0) - (b.clientTs || 0);
101
- });
102
- const keep = n >= sorted.length ? [] : sorted.slice(n);
103
- const db = yield* openDB();
104
- try {
105
- const tx = db.transaction([storeName], "readwrite");
106
- const store = tx.objectStore(storeName);
107
- store.clear();
108
- for (const env of keep) store.add(env);
109
- yield* Effect.promise(() => new Promise((resolve, reject) => {
110
- tx.oncomplete = () => resolve();
111
- tx.onerror = () => reject(tx.error);
112
- }));
113
- } finally {
114
- db.close();
115
- }
116
- }).pipe(Effect.catchAll(() => Effect.void)),
117
- clear: () => withStore("readwrite", (store) => store.clear()).pipe(Effect.as(void 0), Effect.catchAll(() => Effect.void)),
118
- capacity: () => capacity
119
- };
120
- }
121
- function createMemoryStorageAdapter(maxQueueSize = 500) {
122
- const capacity = maxQueueSize;
123
- let buffer = [];
124
- return {
125
- load: () => Effect.succeed(buffer),
126
- save: (envelopes) => Effect.sync(() => {
127
- buffer = envelopes;
128
- }),
129
- append: (envelopes) => Effect.sync(() => {
130
- const next = [...buffer, ...envelopes];
131
- buffer = next.length > capacity ? next.slice(next.length - capacity) : next;
132
- }),
133
- removeByIds: (ids) => Effect.sync(() => {
134
- if (ids.length === 0) return;
135
- const set = new Set(ids);
136
- buffer = buffer.filter((e) => e.uuid ? !set.has(e.uuid) : true);
137
- }),
138
- dropOldest: (n) => Effect.sync(() => {
139
- buffer = n >= buffer.length ? [] : buffer.slice(n);
140
- }),
141
- clear: () => Effect.sync(() => {
142
- buffer = [];
143
- }),
144
- capacity: () => capacity
145
- };
146
- }
147
- /**
148
- * Factory to choose appropriate storage based on offline config.
149
- *
150
- * When offline storage is disabled (default), uses in-memory storage that is
151
- * lost on page refresh. This is the default behavior for performance and privacy.
152
- *
153
- * When offline storage is enabled, uses IndexedDB to persist envelopes across
154
- * page refreshes and retry when connectivity returns. Falls back to in-memory
155
- * if IndexedDB is unavailable.
156
- *
157
- * @param options - Storage adapter options including offline configuration
158
- * @returns The appropriate storage adapter
159
- *
160
- * @example
161
- * // Default: in-memory storage (no persistence)
162
- * const adapter = createStorageAdapter();
163
- *
164
- * @example
165
- * // Enable offline storage for better reliability
166
- * const adapter = createStorageAdapter({
167
- * offline: { enabled: true, maxQueueSize: 100 }
168
- * });
169
- */
170
- function createStorageAdapter(options = {}) {
171
- const { offline } = options;
172
- const maxQueueSize = offline?.maxQueueSize ?? 100;
173
- if (!offline?.enabled) return createMemoryStorageAdapter(maxQueueSize);
174
- const namespace = `${name}:${version}`;
175
- if (typeof indexedDB !== "undefined") return createIndexedDBAdapter(namespace, "envelopes", maxQueueSize);
176
- return createMemoryStorageAdapter(maxQueueSize);
177
- }
178
-
179
- //#endregion
180
- export { createIndexedDBAdapter, 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 { OfflineStorage } from \"@interfere/types/sdk/config\";\nimport 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 interface StorageAdapterOptions {\n /**\n * Offline storage configuration.\n * When enabled, uses IndexedDB for persistence.\n * When disabled (default), uses in-memory storage that's lost on page refresh.\n */\n offline?: OfflineStorage;\n}\n\n// IndexedDB adapter for persistent offline storage\nexport function createIndexedDBAdapter(\n dbName: string,\n storeName: string,\n maxQueueSize = 1000\n): StorageAdapter {\n const capacity = maxQueueSize;\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 - default when offline storage is disabled\nexport function createMemoryStorageAdapter(maxQueueSize = 500): StorageAdapter {\n const capacity = maxQueueSize;\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/**\n * Factory to choose appropriate storage based on offline config.\n *\n * When offline storage is disabled (default), uses in-memory storage that is\n * lost on page refresh. This is the default behavior for performance and privacy.\n *\n * When offline storage is enabled, uses IndexedDB to persist envelopes across\n * page refreshes and retry when connectivity returns. Falls back to in-memory\n * if IndexedDB is unavailable.\n *\n * @param options - Storage adapter options including offline configuration\n * @returns The appropriate storage adapter\n *\n * @example\n * // Default: in-memory storage (no persistence)\n * const adapter = createStorageAdapter();\n *\n * @example\n * // Enable offline storage for better reliability\n * const adapter = createStorageAdapter({\n * offline: { enabled: true, maxQueueSize: 100 }\n * });\n */\nexport function createStorageAdapter(\n options: StorageAdapterOptions = {}\n): StorageAdapter {\n const { offline } = options;\n const maxQueueSize = offline?.maxQueueSize ?? 100;\n\n // Default: in-memory storage when offline is not enabled\n if (!offline?.enabled) {\n return createMemoryStorageAdapter(maxQueueSize);\n }\n\n // Offline enabled: use IndexedDB for persistence\n const sdkName = packageJson.name;\n const sdkVersion = packageJson.version;\n const namespace = `${sdkName}:${sdkVersion}`;\n\n if (typeof indexedDB !== \"undefined\") {\n return createIndexedDBAdapter(namespace, \"envelopes\", maxQueueSize);\n }\n\n // Fallback: in-memory (offline enabled but IndexedDB not available)\n return createMemoryStorageAdapter(maxQueueSize);\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,58 +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
- offline: {
24
- enabled: boolean;
25
- maxQueueSize: number;
26
- };
27
- } & {
28
- proxyUrl: string;
29
- }) | ({
30
- features: {
31
- errors?: boolean | undefined;
32
- replay?: boolean | undefined;
33
- rageClick?: boolean | undefined;
34
- aiSummary?: boolean | undefined;
35
- pageEvents?: boolean | undefined;
36
- serverTracing?: boolean | undefined;
37
- };
38
- metadata: {
39
- buildId: string | null;
40
- releaseId: string | null;
41
- environment: "development" | "preview" | "production" | null;
42
- runtime: "edge" | "browser" | "node" | null;
43
- };
44
- batch: {
45
- size: number;
46
- ms: number;
47
- };
48
- offline: {
49
- enabled: boolean;
50
- maxQueueSize: number;
51
- };
52
- } & {
53
- ingestUrl: string;
54
- surfaceToken: string;
55
- })>;
56
- declare class ConfigTag extends ConfigTag_base {}
57
- //#endregion
58
- 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"}
@@ -1,7 +0,0 @@
1
- import { Context } from "effect";
2
-
3
- //#region src/effect/tags.ts
4
- var ConfigTag = class extends Context.Tag("@interfere/react/Config")() {};
5
-
6
- //#endregion
7
- export { ConfigTag };
@@ -1 +0,0 @@
1
- {"version":3,"file":"tags.mjs","names":[],"sources":["../../src/effect/tags.ts"],"sourcesContent":["import type { Config } from \"@interfere/types/sdk/config\";\n\nimport { Context } from \"effect\";\n\nexport class ConfigTag extends Context.Tag(\"@interfere/react/Config\")<\n ConfigTag,\n Config\n>() {}\n"],"mappings":";;;AAIA,IAAa,YAAb,cAA+B,QAAQ,IAAI,0BAA0B,EAGlE,CAAC"}
@@ -1,7 +0,0 @@
1
- import { Plugin, PluginApiMap } from "../core/schemas.mjs";
2
- import { Config } from "@interfere/types/sdk/config";
3
-
4
- //#region src/hooks/use-runtime-and-plugins.d.ts
5
- declare function useRuntimeAndPlugins(config: Config, plugins?: Plugin[]): Partial<PluginApiMap>;
6
- //#endregion
7
- export { useRuntimeAndPlugins };
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-runtime-and-plugins.d.mts","names":[],"sources":["../../src/hooks/use-runtime-and-plugins.ts"],"sourcesContent":[],"mappings":";;;;iBAqGgB,oBAAA,SACN,kBACE,WACT,QAAQ"}
@@ -1,153 +0,0 @@
1
- "use client";
2
-
3
- import { getRuntime, initConfig } from "../core/runtime/config.mjs";
4
- import { SessionServiceLive } from "../effect/layers/session.layer.mjs";
5
- import { ConfigTag } from "../effect/tags.mjs";
6
- import { ContextServiceLive } from "../effect/layers/context.layer.mjs";
7
- import { deriveIngestTarget } from "../core/runtime/ingest-target.mjs";
8
- import { HttpServiceLive } from "../effect/layers/http.layer.mjs";
9
- import { QueueServiceLive, QueueServiceTag } from "../effect/layers/queue.layer.mjs";
10
- import { withSpan } from "../effect/layers/tracer.layer.mjs";
11
- import { closeSDK, flushQueue, forkWithSDK, isSDKInitialized, runWithSDK, setSDKRuntime } from "../effect/runtime-services.mjs";
12
- import { captureEffect } from "../client.mjs";
13
- import { loadAndSetupPluginsEffect } from "../core/plugins/plugin-loader.mjs";
14
- import { Cause, Effect, Exit, Layer, Runtime, Scope } from "effect";
15
- import { configSchema } from "@interfere/types/sdk/config";
16
- import { useEffect, useRef, useState } from "react";
17
-
18
- //#region src/hooks/use-runtime-and-plugins.ts
19
- const createSDKLayer = (config) => {
20
- const configWithRuntime = {
21
- ...config,
22
- runtime: getRuntime()
23
- };
24
- const configLayer = Layer.succeed(ConfigTag, configWithRuntime);
25
- const contextLayer = ContextServiceLive;
26
- const httpLayer = HttpServiceLive(configWithRuntime);
27
- const sessionLayer = SessionServiceLive;
28
- const queueLayer = QueueServiceLive.pipe(Layer.provide(configLayer), Layer.provide(httpLayer));
29
- return Layer.mergeAll(configLayer, contextLayer, httpLayer, sessionLayer, queueLayer);
30
- };
31
- const initRuntimeServices = async (input) => {
32
- if (isSDKInitialized()) return;
33
- const config = configSchema.parse(input);
34
- initConfig(config);
35
- const scope = await Effect.runPromise(Scope.make());
36
- const runtime = await Effect.runPromise(Layer.toRuntime(createSDKLayer(config)).pipe(Effect.provideService(Scope.Scope, scope)));
37
- setSDKRuntime(scope, runtime);
38
- await Runtime.runPromise(runtime)(Effect.gen(function* () {
39
- yield* Effect.logDebug("Runtime initialized successfully");
40
- yield* Effect.forkDaemon(Effect.gen(function* () {
41
- yield* (yield* QueueServiceTag).startBatchProcessor().pipe(Effect.provideService(Scope.Scope, scope));
42
- }).pipe(Effect.catchAll((error) => Effect.logError("Failed to start batch processor", { error: String(error) }))));
43
- }));
44
- };
45
- function useRuntimeAndPlugins(config, plugins) {
46
- const [pluginApis, setPluginApis] = useState({});
47
- const pluginHandlersRef = useRef([]);
48
- const initRef = useRef(false);
49
- useEffect(() => {
50
- if (typeof window === "undefined" || initRef.current) return;
51
- initRef.current = true;
52
- const runCleanup = (cleanups) => Effect.gen(function* () {
53
- const TIMEOUT_MS = 1500;
54
- yield* Effect.tryPromise({
55
- try: () => flushQueue(TIMEOUT_MS),
56
- catch: (error) => Effect.logDebug("Bounded flush timed out during cleanup", {
57
- timeoutMs: TIMEOUT_MS,
58
- error: String(error)
59
- })
60
- }).pipe(Effect.ignore);
61
- for (const dispose of cleanups) {
62
- yield* Effect.logTrace(`Running cleanup for plugin ${dispose.name}`);
63
- yield* Effect.try({
64
- try: () => dispose(),
65
- catch: (error) => Effect.logDebug("Plugin cleanup failed", { error: String(error) })
66
- }).pipe(Effect.ignore);
67
- }
68
- yield* Effect.logTrace("Closing SDK");
69
- yield* Effect.promise(() => closeSDK());
70
- });
71
- const initialize = async () => {
72
- try {
73
- await initRuntimeServices(config);
74
- deriveIngestTarget(config);
75
- } catch (error) {
76
- console.error("[Interfere SDK] Failed to initialize:", error);
77
- return;
78
- }
79
- const pluginContext = {
80
- capture: captureEffect,
81
- config,
82
- run: (eff) => {
83
- if (!isSDKInitialized()) {
84
- console.warn("[Interfere SDK] Attempted to run effect before SDK initialized");
85
- return;
86
- }
87
- forkWithSDK(eff);
88
- },
89
- span: (label, eff) => {
90
- if (!isSDKInitialized()) {
91
- console.warn("[Interfere SDK] Attempted to run span before SDK initialized");
92
- return;
93
- }
94
- forkWithSDK(withSpan(label, eff));
95
- },
96
- captureNow: (type, payload) => {
97
- if (!isSDKInitialized()) {
98
- console.warn("[Interfere SDK] Attempted to capture event before SDK initialized");
99
- return;
100
- }
101
- forkWithSDK(captureEffect(type, payload));
102
- },
103
- log: {
104
- trace: (...message) => forkWithSDK(Effect.logTrace(...message)),
105
- debug: (...message) => forkWithSDK(Effect.logDebug(...message)),
106
- info: (...message) => forkWithSDK(Effect.logInfo(...message)),
107
- warn: (...message) => forkWithSDK(Effect.logWarning(...message)),
108
- error: (...message) => forkWithSDK(Effect.logError(...message)),
109
- fatal: (...message) => forkWithSDK(Effect.logFatal(...message))
110
- }
111
- };
112
- const result = await runWithSDK(Effect.gen(function* () {
113
- const exit = yield* Effect.exit(loadAndSetupPluginsEffect(config, pluginContext, plugins));
114
- if (Exit.isFailure(exit)) {
115
- const cause = exit.cause;
116
- yield* Effect.logFatal("Failed to load plugins", {
117
- cause: Cause.pretty(cause),
118
- features: config.features,
119
- userPluginCount: Array.isArray(plugins) ? plugins.length : 0
120
- });
121
- return;
122
- }
123
- const { cleanups, apis, keys } = exit.value;
124
- yield* Effect.logDebug(`${keys.size} plugins loaded, ${Object.keys(apis).length} APIs exposed`, {
125
- plugins: Array.from(keys),
126
- apis: Object.keys(apis)
127
- });
128
- yield* (yield* QueueServiceTag).setReady(true);
129
- return {
130
- cleanups,
131
- apis
132
- };
133
- }));
134
- if (result) {
135
- pluginHandlersRef.current = result.cleanups;
136
- setPluginApis(result.apis);
137
- }
138
- };
139
- initialize();
140
- return () => {
141
- if (isSDKInitialized()) runWithSDK(runCleanup(pluginHandlersRef.current)).catch((error) => {
142
- console.error("[Interfere SDK] Provider cleanup failed:", error);
143
- });
144
- else Effect.runPromise(runCleanup(pluginHandlersRef.current)).catch((error) => {
145
- console.error("[Interfere SDK] Provider cleanup failed:", error);
146
- });
147
- };
148
- }, [config, plugins]);
149
- return pluginApis;
150
- }
151
-
152
- //#endregion
153
- export { useRuntimeAndPlugins };
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-runtime-and-plugins.mjs","names":["pluginContext: PluginContext"],"sources":["../../src/hooks/use-runtime-and-plugins.ts"],"sourcesContent":["\"use client\";\n\nimport type { Config } from \"@interfere/types/sdk/config\";\nimport { configSchema } from \"@interfere/types/sdk/config\";\n\nimport { Cause, Effect, Exit, Layer, Runtime, Scope } from \"effect\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { captureEffect } from \"../client.js\";\nimport { loadAndSetupPluginsEffect } from \"../core/plugins/plugin-loader.js\";\nimport { getRuntime, initConfig } from \"../core/runtime/config.js\";\nimport { deriveIngestTarget } from \"../core/runtime/ingest-target.js\";\nimport type { Plugin, PluginApiMap, PluginContext } from \"../core/schemas.js\";\nimport { ContextServiceLive } from \"../effect/layers/context.layer.js\";\nimport { HttpServiceLive } from \"../effect/layers/http.layer.js\";\nimport {\n QueueServiceLive,\n QueueServiceTag,\n} from \"../effect/layers/queue.layer.js\";\nimport { SessionServiceLive } from \"../effect/layers/session.layer.js\";\nimport { withSpan } from \"../effect/layers/tracer.layer.js\";\nimport {\n closeSDK,\n flushQueue,\n forkWithSDK,\n isSDKInitialized,\n runWithSDK,\n setSDKRuntime,\n} from \"../effect/runtime-services.js\";\nimport { ConfigTag } from \"../effect/tags.js\";\n\nconst createSDKLayer = (config: Config) => {\n const configWithRuntime = {\n ...config,\n runtime: getRuntime(),\n };\n\n const configLayer = Layer.succeed(ConfigTag, configWithRuntime);\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\nconst initRuntimeServices = async (input: unknown): Promise<void> => {\n if (isSDKInitialized()) {\n return;\n }\n\n const config = configSchema.parse(input);\n\n // Seed config for runtime consumers that don't use Effect tags\n initConfig(config);\n\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 await Runtime.runPromise(runtime)(\n Effect.gen(function* () {\n yield* Effect.logDebug(\"Runtime initialized successfully\");\n\n // Start batch processor\n yield* Effect.forkDaemon(\n Effect.gen(function* () {\n const queue = yield* QueueServiceTag;\n yield* queue\n .startBatchProcessor()\n .pipe(Effect.provideService(Scope.Scope, scope));\n }).pipe(\n Effect.catchAll((error) =>\n Effect.logError(\"Failed to start batch processor\", {\n error: String(error),\n })\n )\n )\n );\n })\n );\n};\n\n// removed Effect wrapper; plugin loading now handled with runPromise + try/catch in initialize\n\nexport function useRuntimeAndPlugins(\n config: Config,\n plugins?: Plugin[]\n): Partial<PluginApiMap> {\n const [pluginApis, setPluginApis] = useState<Partial<PluginApiMap>>({});\n const pluginHandlersRef = useRef<Array<() => void>>([]);\n const initRef = useRef(false);\n\n useEffect(() => {\n if (typeof window === \"undefined\" || initRef.current) {\n return;\n }\n\n initRef.current = true;\n\n const runCleanup = (cleanups: Array<() => void>) =>\n Effect.gen(function* () {\n const TIMEOUT_MS = 1500;\n\n yield* Effect.tryPromise({\n try: () => flushQueue(TIMEOUT_MS),\n catch: (error) =>\n Effect.logDebug(\"Bounded flush timed out during cleanup\", {\n timeoutMs: TIMEOUT_MS,\n error: String(error),\n }),\n }).pipe(Effect.ignore);\n\n for (const dispose of cleanups) {\n yield* Effect.logTrace(`Running cleanup for plugin ${dispose.name}`);\n\n yield* Effect.try({\n try: () => dispose(),\n catch: (error) =>\n Effect.logDebug(\"Plugin cleanup failed\", {\n error: String(error),\n }),\n }).pipe(Effect.ignore);\n }\n\n yield* Effect.logTrace(\"Closing SDK\");\n\n yield* Effect.promise(() => closeSDK());\n });\n\n const initialize = async () => {\n try {\n await initRuntimeServices(config);\n // Early ingest target validation (fail fast) without singleton reliance\n deriveIngestTarget(config);\n } catch (error) {\n console.error(\"[Interfere SDK] Failed to initialize:\", error);\n return;\n }\n\n const pluginContext: PluginContext = {\n capture: captureEffect,\n config,\n run: (eff) => {\n if (!isSDKInitialized()) {\n console.warn(\n \"[Interfere SDK] Attempted to run effect before SDK initialized\"\n );\n\n return;\n }\n forkWithSDK(eff);\n },\n span: (label, eff) => {\n if (!isSDKInitialized()) {\n console.warn(\n \"[Interfere SDK] Attempted to run span before SDK initialized\"\n );\n\n return;\n }\n forkWithSDK(withSpan(label, eff));\n },\n captureNow: (type, payload) => {\n if (!isSDKInitialized()) {\n console.warn(\n \"[Interfere SDK] Attempted to capture event before SDK initialized\"\n );\n\n return;\n }\n forkWithSDK(captureEffect(type, payload));\n },\n log: {\n trace: (...message) => forkWithSDK(Effect.logTrace(...message)),\n debug: (...message) => forkWithSDK(Effect.logDebug(...message)),\n info: (...message) => forkWithSDK(Effect.logInfo(...message)),\n warn: (...message) => forkWithSDK(Effect.logWarning(...message)),\n error: (...message) => forkWithSDK(Effect.logError(...message)),\n fatal: (...message) => forkWithSDK(Effect.logFatal(...message)),\n },\n };\n\n const result = await runWithSDK(\n Effect.gen(function* () {\n const exit = yield* Effect.exit(\n loadAndSetupPluginsEffect(config, pluginContext, plugins)\n );\n\n if (Exit.isFailure(exit)) {\n const cause = exit.cause;\n\n yield* Effect.logFatal(\"Failed to load plugins\", {\n cause: Cause.pretty(cause),\n features: config.features,\n userPluginCount: Array.isArray(plugins) ? plugins.length : 0,\n });\n\n return;\n }\n\n const { cleanups, apis, keys } = exit.value;\n\n yield* Effect.logDebug(\n `${keys.size} plugins loaded, ${Object.keys(apis).length} APIs exposed`,\n {\n plugins: Array.from(keys),\n apis: Object.keys(apis),\n }\n );\n\n // Signal queue readiness now that plugins have loaded\n const queue = yield* QueueServiceTag;\n yield* queue.setReady(true);\n\n return { cleanups, apis };\n })\n );\n\n if (result) {\n pluginHandlersRef.current = result.cleanups;\n\n setPluginApis(result.apis);\n }\n };\n\n // biome-ignore lint/complexity/noVoid: fire-and-forget initialization\n void initialize();\n\n return () => {\n if (isSDKInitialized()) {\n runWithSDK(runCleanup(pluginHandlersRef.current)).catch((error) => {\n console.error(\"[Interfere SDK] Provider cleanup failed:\", error);\n });\n } else {\n // If SDK never initialized, run cleanup directly\n Effect.runPromise(runCleanup(pluginHandlersRef.current)).catch(\n (error) => {\n console.error(\"[Interfere SDK] Provider cleanup failed:\", error);\n }\n );\n }\n };\n }, [config, plugins]);\n\n return pluginApis;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA+BA,MAAM,kBAAkB,WAAmB;CACzC,MAAM,oBAAoB;EACxB,GAAG;EACH,SAAS,YAAY;EACtB;CAED,MAAM,cAAc,MAAM,QAAQ,WAAW,kBAAkB;CAC/D,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;;AAGH,MAAM,sBAAsB,OAAO,UAAkC;AACnE,KAAI,kBAAkB,CACpB;CAGF,MAAM,SAAS,aAAa,MAAM,MAAM;AAGxC,YAAW,OAAO;CAElB,MAAM,QAAQ,MAAM,OAAO,WAAW,MAAM,MAAM,CAAC;CAEnD,MAAM,UAAU,MAAM,OAAO,WAC3B,MAAM,UAAU,eAAe,OAAO,CAAC,CAAC,KACtC,OAAO,eAAe,MAAM,OAAO,MAAM,CAC1C,CACF;AAED,eAAc,OAAO,QAAQ;AAE7B,OAAM,QAAQ,WAAW,QAAQ,CAC/B,OAAO,IAAI,aAAa;AACtB,SAAO,OAAO,SAAS,mCAAmC;AAG1D,SAAO,OAAO,WACZ,OAAO,IAAI,aAAa;AAEtB,WADc,OAAO,iBAElB,qBAAqB,CACrB,KAAK,OAAO,eAAe,MAAM,OAAO,MAAM,CAAC;IAClD,CAAC,KACD,OAAO,UAAU,UACf,OAAO,SAAS,mCAAmC,EACjD,OAAO,OAAO,MAAM,EACrB,CAAC,CACH,CACF,CACF;GACD,CACH;;AAKH,SAAgB,qBACd,QACA,SACuB;CACvB,MAAM,CAAC,YAAY,iBAAiB,SAAgC,EAAE,CAAC;CACvE,MAAM,oBAAoB,OAA0B,EAAE,CAAC;CACvD,MAAM,UAAU,OAAO,MAAM;AAE7B,iBAAgB;AACd,MAAI,OAAO,WAAW,eAAe,QAAQ,QAC3C;AAGF,UAAQ,UAAU;EAElB,MAAM,cAAc,aAClB,OAAO,IAAI,aAAa;GACtB,MAAM,aAAa;AAEnB,UAAO,OAAO,WAAW;IACvB,WAAW,WAAW,WAAW;IACjC,QAAQ,UACN,OAAO,SAAS,0CAA0C;KACxD,WAAW;KACX,OAAO,OAAO,MAAM;KACrB,CAAC;IACL,CAAC,CAAC,KAAK,OAAO,OAAO;AAEtB,QAAK,MAAM,WAAW,UAAU;AAC9B,WAAO,OAAO,SAAS,8BAA8B,QAAQ,OAAO;AAEpE,WAAO,OAAO,IAAI;KAChB,WAAW,SAAS;KACpB,QAAQ,UACN,OAAO,SAAS,yBAAyB,EACvC,OAAO,OAAO,MAAM,EACrB,CAAC;KACL,CAAC,CAAC,KAAK,OAAO,OAAO;;AAGxB,UAAO,OAAO,SAAS,cAAc;AAErC,UAAO,OAAO,cAAc,UAAU,CAAC;IACvC;EAEJ,MAAM,aAAa,YAAY;AAC7B,OAAI;AACF,UAAM,oBAAoB,OAAO;AAEjC,uBAAmB,OAAO;YACnB,OAAO;AACd,YAAQ,MAAM,yCAAyC,MAAM;AAC7D;;GAGF,MAAMA,gBAA+B;IACnC,SAAS;IACT;IACA,MAAM,QAAQ;AACZ,SAAI,CAAC,kBAAkB,EAAE;AACvB,cAAQ,KACN,iEACD;AAED;;AAEF,iBAAY,IAAI;;IAElB,OAAO,OAAO,QAAQ;AACpB,SAAI,CAAC,kBAAkB,EAAE;AACvB,cAAQ,KACN,+DACD;AAED;;AAEF,iBAAY,SAAS,OAAO,IAAI,CAAC;;IAEnC,aAAa,MAAM,YAAY;AAC7B,SAAI,CAAC,kBAAkB,EAAE;AACvB,cAAQ,KACN,oEACD;AAED;;AAEF,iBAAY,cAAc,MAAM,QAAQ,CAAC;;IAE3C,KAAK;KACH,QAAQ,GAAG,YAAY,YAAY,OAAO,SAAS,GAAG,QAAQ,CAAC;KAC/D,QAAQ,GAAG,YAAY,YAAY,OAAO,SAAS,GAAG,QAAQ,CAAC;KAC/D,OAAO,GAAG,YAAY,YAAY,OAAO,QAAQ,GAAG,QAAQ,CAAC;KAC7D,OAAO,GAAG,YAAY,YAAY,OAAO,WAAW,GAAG,QAAQ,CAAC;KAChE,QAAQ,GAAG,YAAY,YAAY,OAAO,SAAS,GAAG,QAAQ,CAAC;KAC/D,QAAQ,GAAG,YAAY,YAAY,OAAO,SAAS,GAAG,QAAQ,CAAC;KAChE;IACF;GAED,MAAM,SAAS,MAAM,WACnB,OAAO,IAAI,aAAa;IACtB,MAAM,OAAO,OAAO,OAAO,KACzB,0BAA0B,QAAQ,eAAe,QAAQ,CAC1D;AAED,QAAI,KAAK,UAAU,KAAK,EAAE;KACxB,MAAM,QAAQ,KAAK;AAEnB,YAAO,OAAO,SAAS,0BAA0B;MAC/C,OAAO,MAAM,OAAO,MAAM;MAC1B,UAAU,OAAO;MACjB,iBAAiB,MAAM,QAAQ,QAAQ,GAAG,QAAQ,SAAS;MAC5D,CAAC;AAEF;;IAGF,MAAM,EAAE,UAAU,MAAM,SAAS,KAAK;AAEtC,WAAO,OAAO,SACZ,GAAG,KAAK,KAAK,mBAAmB,OAAO,KAAK,KAAK,CAAC,OAAO,gBACzD;KACE,SAAS,MAAM,KAAK,KAAK;KACzB,MAAM,OAAO,KAAK,KAAK;KACxB,CACF;AAID,YADc,OAAO,iBACR,SAAS,KAAK;AAE3B,WAAO;KAAE;KAAU;KAAM;KACzB,CACH;AAED,OAAI,QAAQ;AACV,sBAAkB,UAAU,OAAO;AAEnC,kBAAc,OAAO,KAAK;;;AAK9B,EAAK,YAAY;AAEjB,eAAa;AACX,OAAI,kBAAkB,CACpB,YAAW,WAAW,kBAAkB,QAAQ,CAAC,CAAC,OAAO,UAAU;AACjE,YAAQ,MAAM,4CAA4C,MAAM;KAChE;OAGF,QAAO,WAAW,WAAW,kBAAkB,QAAQ,CAAC,CAAC,OACtD,UAAU;AACT,YAAQ,MAAM,4CAA4C,MAAM;KAEnE;;IAGJ,CAAC,QAAQ,QAAQ,CAAC;AAErB,QAAO"}