@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.
- package/README.md +90 -0
- package/dist/error-boundary.d.mts +27 -0
- package/dist/error-boundary.d.mts.map +1 -0
- package/dist/error-boundary.mjs +42 -0
- package/dist/error-boundary.mjs.map +1 -0
- package/dist/internal/client.d.mts +13 -0
- package/dist/internal/client.d.mts.map +1 -0
- package/dist/internal/client.mjs +80 -0
- package/dist/internal/client.mjs.map +1 -0
- package/dist/internal/config.d.mts +9 -0
- package/dist/internal/config.d.mts.map +1 -0
- package/dist/internal/config.mjs +27 -0
- package/dist/internal/config.mjs.map +1 -0
- package/dist/internal/context.d.mts +6 -0
- package/dist/internal/context.d.mts.map +1 -0
- package/dist/internal/context.mjs +32 -0
- package/dist/internal/context.mjs.map +1 -0
- package/dist/internal/envelope.d.mts +14 -0
- package/dist/internal/envelope.d.mts.map +1 -0
- package/dist/internal/envelope.mjs +20 -0
- package/dist/internal/envelope.mjs.map +1 -0
- package/dist/internal/errors.d.mts +4 -0
- package/dist/internal/errors.d.mts.map +1 -0
- package/dist/internal/errors.mjs +4 -0
- package/dist/internal/errors.mjs.map +1 -0
- package/dist/internal/sw.d.mts +4 -0
- package/dist/internal/sw.d.mts.map +1 -0
- package/dist/internal/sw.mjs +10 -0
- package/dist/internal/sw.mjs.map +1 -0
- package/dist/plugins/errors.d.mts +6 -0
- package/dist/plugins/errors.d.mts.map +1 -0
- package/dist/plugins/errors.mjs +59 -0
- package/dist/plugins/errors.mjs.map +1 -0
- package/dist/plugins/lib/loader.d.mts +9 -0
- package/dist/plugins/lib/loader.d.mts.map +1 -0
- package/dist/plugins/lib/loader.mjs +47 -0
- package/dist/plugins/lib/loader.mjs.map +1 -0
- package/dist/plugins/lib/types.d.mts +14 -0
- package/dist/plugins/lib/types.d.mts.map +1 -0
- package/dist/plugins/lib/types.mjs +1 -0
- package/dist/plugins/pages.d.mts +6 -0
- package/dist/plugins/pages.d.mts.map +1 -0
- package/dist/plugins/pages.mjs +102 -0
- package/dist/plugins/pages.mjs.map +1 -0
- package/dist/plugins/rage-clicks.d.mts +6 -0
- package/dist/plugins/rage-clicks.d.mts.map +1 -0
- package/dist/plugins/rage-clicks.mjs +53 -0
- package/dist/plugins/rage-clicks.mjs.map +1 -0
- package/dist/plugins/replay.d.mts +6 -0
- package/dist/plugins/replay.d.mts.map +1 -0
- package/dist/plugins/replay.mjs +62 -0
- package/dist/plugins/replay.mjs.map +1 -0
- package/dist/provider.d.mts +17 -11
- package/dist/provider.d.mts.map +1 -1
- package/dist/provider.mjs +18 -17
- package/dist/provider.mjs.map +1 -1
- package/dist/tracking/api.d.mts +22 -0
- package/dist/tracking/api.d.mts.map +1 -0
- package/dist/tracking/api.mjs +88 -0
- package/dist/tracking/api.mjs.map +1 -0
- package/dist/tracking/session.d.mts +19 -0
- package/dist/tracking/session.d.mts.map +1 -0
- package/dist/tracking/session.mjs +92 -0
- package/dist/tracking/session.mjs.map +1 -0
- package/dist/tracking/visitor.d.mts +6 -0
- package/dist/tracking/visitor.d.mts.map +1 -0
- package/dist/tracking/visitor.mjs +35 -0
- package/dist/tracking/visitor.mjs.map +1 -0
- package/dist/transport/http.d.mts +15 -0
- package/dist/transport/http.d.mts.map +1 -0
- package/dist/transport/http.mjs +56 -0
- package/dist/transport/http.mjs.map +1 -0
- package/dist/transport/queue.d.mts +25 -0
- package/dist/transport/queue.d.mts.map +1 -0
- package/dist/transport/queue.mjs +60 -0
- package/dist/transport/queue.mjs.map +1 -0
- package/dist/util/log.d.mts +13 -0
- package/dist/util/log.d.mts.map +1 -0
- package/dist/util/log.mjs +37 -0
- package/dist/util/log.mjs.map +1 -0
- package/package.json +43 -66
- package/dist/client.d.mts +0 -15
- package/dist/client.d.mts.map +0 -1
- package/dist/client.mjs +0 -75
- package/dist/client.mjs.map +0 -1
- package/dist/core/events/event-registry.d.mts +0 -23
- package/dist/core/events/event-registry.d.mts.map +0 -1
- package/dist/core/events/event-registry.mjs +0 -32
- package/dist/core/events/event-registry.mjs.map +0 -1
- package/dist/core/events/plugin-event-types.d.mts +0 -92
- package/dist/core/events/plugin-event-types.d.mts.map +0 -1
- package/dist/core/events/plugin-event-types.mjs +0 -25
- package/dist/core/events/plugin-event-types.mjs.map +0 -1
- package/dist/core/plugins/dom-utils.d.mts +0 -9
- package/dist/core/plugins/dom-utils.d.mts.map +0 -1
- package/dist/core/plugins/dom-utils.mjs +0 -25
- package/dist/core/plugins/dom-utils.mjs.map +0 -1
- package/dist/core/plugins/impl/ai-summary.d.mts +0 -6
- package/dist/core/plugins/impl/ai-summary.d.mts.map +0 -1
- package/dist/core/plugins/impl/ai-summary.mjs +0 -122
- package/dist/core/plugins/impl/ai-summary.mjs.map +0 -1
- package/dist/core/plugins/impl/errors.d.mts +0 -9
- package/dist/core/plugins/impl/errors.d.mts.map +0 -1
- package/dist/core/plugins/impl/errors.mjs +0 -160
- package/dist/core/plugins/impl/errors.mjs.map +0 -1
- package/dist/core/plugins/impl/page-events.d.mts +0 -15
- package/dist/core/plugins/impl/page-events.d.mts.map +0 -1
- package/dist/core/plugins/impl/page-events.mjs +0 -131
- package/dist/core/plugins/impl/page-events.mjs.map +0 -1
- package/dist/core/plugins/impl/rage-click.d.mts +0 -6
- package/dist/core/plugins/impl/rage-click.d.mts.map +0 -1
- package/dist/core/plugins/impl/rage-click.mjs +0 -53
- package/dist/core/plugins/impl/rage-click.mjs.map +0 -1
- package/dist/core/plugins/impl/replay.d.mts +0 -9
- package/dist/core/plugins/impl/replay.d.mts.map +0 -1
- package/dist/core/plugins/impl/replay.mjs +0 -144
- package/dist/core/plugins/impl/replay.mjs.map +0 -1
- package/dist/core/plugins/impl/server-tracing.d.mts +0 -7
- package/dist/core/plugins/impl/server-tracing.d.mts.map +0 -1
- package/dist/core/plugins/impl/server-tracing.mjs +0 -160
- package/dist/core/plugins/impl/server-tracing.mjs.map +0 -1
- package/dist/core/plugins/plugin-event-system.d.mts +0 -47
- package/dist/core/plugins/plugin-event-system.d.mts.map +0 -1
- package/dist/core/plugins/plugin-event-system.mjs +0 -75
- package/dist/core/plugins/plugin-event-system.mjs.map +0 -1
- package/dist/core/plugins/plugin-loader.d.mts +0 -22
- package/dist/core/plugins/plugin-loader.d.mts.map +0 -1
- package/dist/core/plugins/plugin-loader.mjs +0 -142
- package/dist/core/plugins/plugin-loader.mjs.map +0 -1
- package/dist/core/runtime/config.d.mts +0 -14
- package/dist/core/runtime/config.d.mts.map +0 -1
- package/dist/core/runtime/config.mjs +0 -39
- package/dist/core/runtime/config.mjs.map +0 -1
- package/dist/core/runtime/context.d.mts +0 -25
- package/dist/core/runtime/context.d.mts.map +0 -1
- package/dist/core/runtime/context.mjs +0 -48
- package/dist/core/runtime/context.mjs.map +0 -1
- package/dist/core/runtime/ingest-target.d.mts +0 -10
- package/dist/core/runtime/ingest-target.d.mts.map +0 -1
- package/dist/core/runtime/ingest-target.mjs +0 -15
- package/dist/core/runtime/ingest-target.mjs.map +0 -1
- package/dist/core/runtime/native-fetch.d.mts +0 -32
- package/dist/core/runtime/native-fetch.d.mts.map +0 -1
- package/dist/core/runtime/native-fetch.mjs +0 -49
- package/dist/core/runtime/native-fetch.mjs.map +0 -1
- package/dist/core/schemas.d.mts +0 -85
- package/dist/core/schemas.d.mts.map +0 -1
- package/dist/core/schemas.mjs +0 -1
- package/dist/effect/build-envelope.d.mts +0 -9
- package/dist/effect/build-envelope.d.mts.map +0 -1
- package/dist/effect/build-envelope.mjs +0 -29
- package/dist/effect/build-envelope.mjs.map +0 -1
- package/dist/effect/errors.d.mts +0 -36
- package/dist/effect/errors.d.mts.map +0 -1
- package/dist/effect/errors.mjs +0 -10
- package/dist/effect/errors.mjs.map +0 -1
- package/dist/effect/layers/config.layer.d.mts +0 -13
- package/dist/effect/layers/config.layer.d.mts.map +0 -1
- package/dist/effect/layers/config.layer.mjs +0 -21
- package/dist/effect/layers/config.layer.mjs.map +0 -1
- package/dist/effect/layers/context.layer.d.mts +0 -12
- package/dist/effect/layers/context.layer.d.mts.map +0 -1
- package/dist/effect/layers/context.layer.mjs +0 -14
- package/dist/effect/layers/context.layer.mjs.map +0 -1
- package/dist/effect/layers/http.layer.d.mts +0 -21
- package/dist/effect/layers/http.layer.d.mts.map +0 -1
- package/dist/effect/layers/http.layer.mjs +0 -114
- package/dist/effect/layers/http.layer.mjs.map +0 -1
- package/dist/effect/layers/queue.layer.d.mts +0 -30
- package/dist/effect/layers/queue.layer.d.mts.map +0 -1
- package/dist/effect/layers/queue.layer.mjs +0 -258
- package/dist/effect/layers/queue.layer.mjs.map +0 -1
- package/dist/effect/layers/session.layer.d.mts +0 -26
- package/dist/effect/layers/session.layer.d.mts.map +0 -1
- package/dist/effect/layers/session.layer.mjs +0 -126
- package/dist/effect/layers/session.layer.mjs.map +0 -1
- package/dist/effect/layers/storage.layer.d.mts +0 -50
- package/dist/effect/layers/storage.layer.d.mts.map +0 -1
- package/dist/effect/layers/storage.layer.mjs +0 -180
- package/dist/effect/layers/storage.layer.mjs.map +0 -1
- package/dist/effect/layers/tracer.layer.d.mts +0 -9
- package/dist/effect/layers/tracer.layer.d.mts.map +0 -1
- package/dist/effect/layers/tracer.layer.mjs +0 -11
- package/dist/effect/layers/tracer.layer.mjs.map +0 -1
- package/dist/effect/runtime-services.d.mts +0 -22
- package/dist/effect/runtime-services.d.mts.map +0 -1
- package/dist/effect/runtime-services.mjs +0 -76
- package/dist/effect/runtime-services.mjs.map +0 -1
- package/dist/effect/tags.d.mts +0 -58
- package/dist/effect/tags.d.mts.map +0 -1
- package/dist/effect/tags.mjs +0 -7
- package/dist/effect/tags.mjs.map +0 -1
- package/dist/hooks/use-runtime-and-plugins.d.mts +0 -7
- package/dist/hooks/use-runtime-and-plugins.d.mts.map +0 -1
- package/dist/hooks/use-runtime-and-plugins.mjs +0 -153
- package/dist/hooks/use-runtime-and-plugins.mjs.map +0 -1
- package/dist/hooks/use-session.d.mts +0 -40
- package/dist/hooks/use-session.d.mts.map +0 -1
- package/dist/hooks/use-session.mjs +0 -96
- package/dist/hooks/use-session.mjs.map +0 -1
- package/dist/package.mjs +0 -100
- package/dist/package.mjs.map +0 -1
- package/dist/server/auth.d.mts +0 -11
- package/dist/server/auth.d.mts.map +0 -1
- package/dist/server/auth.mjs +0 -36
- package/dist/server/auth.mjs.map +0 -1
- package/dist/server/capture.d.mts +0 -18
- package/dist/server/capture.d.mts.map +0 -1
- package/dist/server/capture.mjs +0 -105
- 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"}
|
package/dist/effect/tags.d.mts
DELETED
|
@@ -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"}
|
package/dist/effect/tags.mjs
DELETED
package/dist/effect/tags.mjs.map
DELETED
|
@@ -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":"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"}
|