@interfere/react 0.1.0-alpha.6 → 0.2.0-alpha.2
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 +38 -64
- package/dist/client.d.mts +0 -8
- package/dist/client.d.mts.map +0 -1
- package/dist/client.mjs +0 -14
- package/dist/client.mjs.map +0 -1
- package/dist/core/events/define-event.d.mts +0 -12
- package/dist/core/events/define-event.d.mts.map +0 -1
- package/dist/core/events/define-event.mjs +0 -39
- package/dist/core/events/define-event.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 -130
- 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/define-plugin.d.mts +0 -43
- package/dist/core/plugins/define-plugin.d.mts.map +0 -1
- package/dist/core/plugins/define-plugin.mjs +0 -23
- package/dist/core/plugins/define-plugin.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/ai-summary-plugin-api.d.mts +0 -18
- package/dist/core/plugins/impl/ai-summary/ai-summary-plugin-api.d.mts.map +0 -1
- package/dist/core/plugins/impl/ai-summary/ai-summary-plugin-api.mjs +0 -17
- package/dist/core/plugins/impl/ai-summary/ai-summary-plugin-api.mjs.map +0 -1
- package/dist/core/plugins/impl/ai-summary/plugin.d.mts +0 -6
- package/dist/core/plugins/impl/ai-summary/plugin.d.mts.map +0 -1
- package/dist/core/plugins/impl/ai-summary/plugin.mjs +0 -151
- package/dist/core/plugins/impl/ai-summary/plugin.mjs.map +0 -1
- package/dist/core/plugins/impl/errors/errors-plugin-api.d.mts +0 -17
- package/dist/core/plugins/impl/errors/errors-plugin-api.d.mts.map +0 -1
- package/dist/core/plugins/impl/errors/errors-plugin-api.mjs +0 -58
- package/dist/core/plugins/impl/errors/errors-plugin-api.mjs.map +0 -1
- package/dist/core/plugins/impl/errors/logic.d.mts +0 -15
- package/dist/core/plugins/impl/errors/logic.d.mts.map +0 -1
- package/dist/core/plugins/impl/errors/logic.mjs +0 -48
- package/dist/core/plugins/impl/errors/logic.mjs.map +0 -1
- package/dist/core/plugins/impl/errors/patches.d.mts +0 -13
- package/dist/core/plugins/impl/errors/patches.d.mts.map +0 -1
- package/dist/core/plugins/impl/errors/patches.mjs +0 -43
- package/dist/core/plugins/impl/errors/patches.mjs.map +0 -1
- package/dist/core/plugins/impl/errors/plugin.d.mts +0 -9
- package/dist/core/plugins/impl/errors/plugin.d.mts.map +0 -1
- package/dist/core/plugins/impl/errors/plugin.mjs +0 -91
- package/dist/core/plugins/impl/errors/plugin.mjs.map +0 -1
- package/dist/core/plugins/impl/page-events/page-events-plugin-api.d.mts +0 -19
- package/dist/core/plugins/impl/page-events/page-events-plugin-api.d.mts.map +0 -1
- package/dist/core/plugins/impl/page-events/page-events-plugin-api.mjs +0 -38
- package/dist/core/plugins/impl/page-events/page-events-plugin-api.mjs.map +0 -1
- package/dist/core/plugins/impl/page-events/plugin.d.mts +0 -6
- package/dist/core/plugins/impl/page-events/plugin.d.mts.map +0 -1
- package/dist/core/plugins/impl/page-events/plugin.mjs +0 -95
- package/dist/core/plugins/impl/page-events/plugin.mjs.map +0 -1
- package/dist/core/plugins/impl/rage-click/plugin.d.mts +0 -6
- package/dist/core/plugins/impl/rage-click/plugin.d.mts.map +0 -1
- package/dist/core/plugins/impl/rage-click/plugin.mjs +0 -38
- package/dist/core/plugins/impl/rage-click/plugin.mjs.map +0 -1
- package/dist/core/plugins/impl/rage-click/rage-click.layer.d.mts +0 -9
- package/dist/core/plugins/impl/rage-click/rage-click.layer.d.mts.map +0 -1
- package/dist/core/plugins/impl/rage-click/rage-click.layer.mjs +0 -35
- package/dist/core/plugins/impl/rage-click/rage-click.layer.mjs.map +0 -1
- package/dist/core/plugins/impl/rage-click/rage-click.service.d.mts +0 -16
- package/dist/core/plugins/impl/rage-click/rage-click.service.d.mts.map +0 -1
- package/dist/core/plugins/impl/rage-click/rage-click.service.mjs +0 -7
- package/dist/core/plugins/impl/rage-click/rage-click.service.mjs.map +0 -1
- package/dist/core/plugins/impl/rage-click/rage-click.test-layer.d.mts +0 -16
- package/dist/core/plugins/impl/rage-click/rage-click.test-layer.d.mts.map +0 -1
- package/dist/core/plugins/impl/rage-click/rage-click.test-layer.mjs +0 -18
- package/dist/core/plugins/impl/rage-click/rage-click.test-layer.mjs.map +0 -1
- package/dist/core/plugins/impl/replay/plugin.d.mts +0 -9
- package/dist/core/plugins/impl/replay/plugin.d.mts.map +0 -1
- package/dist/core/plugins/impl/replay/plugin.mjs +0 -83
- package/dist/core/plugins/impl/replay/plugin.mjs.map +0 -1
- package/dist/core/plugins/impl/replay/replay-plugin-api.d.mts +0 -18
- package/dist/core/plugins/impl/replay/replay-plugin-api.d.mts.map +0 -1
- package/dist/core/plugins/impl/replay/replay-plugin-api.mjs +0 -50
- package/dist/core/plugins/impl/replay/replay-plugin-api.mjs.map +0 -1
- package/dist/core/plugins/impl/server-tracing/plugin.d.mts +0 -13
- package/dist/core/plugins/impl/server-tracing/plugin.d.mts.map +0 -1
- package/dist/core/plugins/impl/server-tracing/plugin.mjs +0 -75
- package/dist/core/plugins/impl/server-tracing/plugin.mjs.map +0 -1
- package/dist/core/plugins/impl/server-tracing/server-tracing-plugin-api.d.mts +0 -16
- package/dist/core/plugins/impl/server-tracing/server-tracing-plugin-api.d.mts.map +0 -1
- package/dist/core/plugins/impl/server-tracing/server-tracing-plugin-api.mjs +0 -17
- package/dist/core/plugins/impl/server-tracing/server-tracing-plugin-api.mjs.map +0 -1
- package/dist/core/plugins/impl/server-tracing/tracing-logic.d.mts +0 -29
- package/dist/core/plugins/impl/server-tracing/tracing-logic.d.mts.map +0 -1
- package/dist/core/plugins/impl/server-tracing/tracing-logic.mjs +0 -55
- package/dist/core/plugins/impl/server-tracing/tracing-logic.mjs.map +0 -1
- package/dist/core/plugins/plugin-loader.d.mts +0 -75
- package/dist/core/plugins/plugin-loader.d.mts.map +0 -1
- package/dist/core/plugins/plugin-loader.mjs +0 -79
- package/dist/core/plugins/plugin-loader.mjs.map +0 -1
- package/dist/core/plugins/services/event-capture.d.mts +0 -12
- package/dist/core/plugins/services/event-capture.d.mts.map +0 -1
- package/dist/core/plugins/services/event-capture.layer.d.mts +0 -11
- package/dist/core/plugins/services/event-capture.layer.d.mts.map +0 -1
- package/dist/core/plugins/services/event-capture.layer.mjs +0 -79
- package/dist/core/plugins/services/event-capture.layer.mjs.map +0 -1
- package/dist/core/plugins/services/event-capture.mjs +0 -7
- package/dist/core/plugins/services/event-capture.mjs.map +0 -1
- package/dist/core/plugins/services/event-capture.test-layer.d.mts +0 -17
- package/dist/core/plugins/services/event-capture.test-layer.d.mts.map +0 -1
- package/dist/core/plugins/services/event-capture.test-layer.mjs +0 -21
- package/dist/core/plugins/services/event-capture.test-layer.mjs.map +0 -1
- package/dist/core/plugins/services/plugin-config.d.mts +0 -11
- package/dist/core/plugins/services/plugin-config.d.mts.map +0 -1
- package/dist/core/plugins/services/plugin-config.mjs +0 -7
- package/dist/core/plugins/services/plugin-config.mjs.map +0 -1
- package/dist/core/plugins/services/plugin-config.test-layer.d.mts +0 -60
- package/dist/core/plugins/services/plugin-config.test-layer.d.mts.map +0 -1
- package/dist/core/plugins/services/plugin-config.test-layer.mjs +0 -8
- package/dist/core/plugins/services/plugin-config.test-layer.mjs.map +0 -1
- package/dist/core/plugins/services/plugin-logger.d.mts +0 -14
- package/dist/core/plugins/services/plugin-logger.d.mts.map +0 -1
- package/dist/core/plugins/services/plugin-logger.mjs +0 -7
- package/dist/core/plugins/services/plugin-logger.mjs.map +0 -1
- package/dist/core/plugins/services/plugin-logger.test-layer.d.mts +0 -18
- package/dist/core/plugins/services/plugin-logger.test-layer.d.mts.map +0 -1
- package/dist/core/plugins/services/plugin-logger.test-layer.mjs +0 -28
- package/dist/core/plugins/services/plugin-logger.test-layer.mjs.map +0 -1
- package/dist/core/plugins/services/plugin-runtime.d.mts +0 -10
- package/dist/core/plugins/services/plugin-runtime.d.mts.map +0 -1
- package/dist/core/plugins/services/plugin-runtime.mjs +0 -7
- package/dist/core/plugins/services/plugin-runtime.mjs.map +0 -1
- package/dist/core/plugins/services/plugin-runtime.test-layer.d.mts +0 -16
- package/dist/core/plugins/services/plugin-runtime.test-layer.d.mts.map +0 -1
- package/dist/core/plugins/services/plugin-runtime.test-layer.mjs +0 -21
- package/dist/core/plugins/services/plugin-runtime.test-layer.mjs.map +0 -1
- package/dist/core/plugins/services/session-info.d.mts +0 -11
- package/dist/core/plugins/services/session-info.d.mts.map +0 -1
- package/dist/core/plugins/services/session-info.mjs +0 -7
- package/dist/core/plugins/services/session-info.mjs.map +0 -1
- package/dist/core/plugins/services/session-info.test-layer.d.mts +0 -18
- package/dist/core/plugins/services/session-info.test-layer.d.mts.map +0 -1
- package/dist/core/plugins/services/session-info.test-layer.mjs +0 -20
- package/dist/core/plugins/services/session-info.test-layer.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 -33
- package/dist/core/runtime/config.mjs.map +0 -1
- package/dist/core/runtime/context.d.mts +0 -50
- package/dist/core/runtime/context.d.mts.map +0 -1
- package/dist/core/runtime/context.mjs +0 -46
- 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 -26
- package/dist/core/schemas.d.mts.map +0 -1
- package/dist/core/schemas.mjs +0 -1
- package/dist/effect/errors.d.mts +0 -22
- package/dist/effect/errors.d.mts.map +0 -1
- package/dist/effect/errors.mjs +0 -17
- package/dist/effect/errors.mjs.map +0 -1
- package/dist/effect/layers/circuit-breaker.layer.d.mts +0 -9
- package/dist/effect/layers/circuit-breaker.layer.d.mts.map +0 -1
- package/dist/effect/layers/circuit-breaker.layer.mjs +0 -9
- package/dist/effect/layers/circuit-breaker.layer.mjs.map +0 -1
- package/dist/effect/layers/circuit-breaker.layer.test-layer.d.mts +0 -18
- package/dist/effect/layers/circuit-breaker.layer.test-layer.d.mts.map +0 -1
- package/dist/effect/layers/circuit-breaker.layer.test-layer.mjs +0 -43
- package/dist/effect/layers/circuit-breaker.layer.test-layer.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 -118
- package/dist/effect/layers/http.layer.mjs.map +0 -1
- package/dist/effect/layers/queue.layer.d.mts +0 -31
- package/dist/effect/layers/queue.layer.d.mts.map +0 -1
- package/dist/effect/layers/queue.layer.mjs +0 -257
- package/dist/effect/layers/queue.layer.mjs.map +0 -1
- package/dist/effect/layers/queue.layer.test-layer.d.mts +0 -19
- package/dist/effect/layers/queue.layer.test-layer.d.mts.map +0 -1
- package/dist/effect/layers/queue.layer.test-layer.mjs +0 -44
- package/dist/effect/layers/queue.layer.test-layer.mjs.map +0 -1
- package/dist/effect/layers/session.layer.d.mts +0 -34
- package/dist/effect/layers/session.layer.d.mts.map +0 -1
- package/dist/effect/layers/session.layer.mjs +0 -127
- 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/test-utils.d.mts +0 -19
- package/dist/effect/layers/test-utils.d.mts.map +0 -1
- package/dist/effect/layers/test-utils.mjs +0 -32
- package/dist/effect/layers/test-utils.mjs.map +0 -1
- package/dist/effect/runtime-services.d.mts +0 -23
- package/dist/effect/runtime-services.d.mts.map +0 -1
- package/dist/effect/runtime-services.mjs +0 -79
- 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 -121
- 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 -103
- package/dist/package.mjs.map +0 -1
- package/dist/server/auth.d.mts +0 -15
- package/dist/server/auth.d.mts.map +0 -1
- package/dist/server/auth.mjs +0 -45
- package/dist/server/auth.mjs.map +0 -1
- package/dist/server/capture.d.mts +0 -34
- package/dist/server/capture.d.mts.map +0 -1
- package/dist/server/capture.mjs +0 -172
- package/dist/server/capture.mjs.map +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://interfere.com">
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://qyzkf4cgb8ydxtq1.public.blob.vercel-storage.com/v2/header/logo-dark.png">
|
|
5
|
+
<img src="https://qyzkf4cgb8ydxtq1.public.blob.vercel-storage.com/v2/header/logo-light.png" height="64">
|
|
6
|
+
</picture>
|
|
7
|
+
</a>
|
|
8
|
+
<h1 align="center">@interfere/react</h1>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://www.npmjs.com/package/@interfere/react"><img src="https://img.shields.io/npm/v/@interfere/react.svg" /></a>
|
|
13
|
+
<a href="https://github.com/interfere-inc/interfere/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@interfere/react.svg" /></a>
|
|
14
|
+
<a href="https://www.npmjs.com/package/@interfere/react"><img src="https://img.shields.io/npm/dm/@interfere/react.svg" /></a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
Client-side React SDK for <a href="https://interfere.com">Interfere</a> — error tracking, session replay, and analytics.
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
<p align="center">
|
|
22
|
+
<a href="https://interfere.com/docs">Documentation</a>
|
|
23
|
+
·
|
|
24
|
+
<a href="https://github.com/interfere-inc/interfere/issues/new">Report a Bug</a>
|
|
25
|
+
·
|
|
26
|
+
<a href="mailto:support@interfere.com">Get Help</a>
|
|
27
|
+
</p>
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
> **Using Next.js?** You probably want [`@interfere/next`](https://www.npmjs.com/package/@interfere/next) instead — This is currently a work-in-progress that will add support for Vite and other React frameworks.
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install @interfere/react
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Prerequisites
|
|
40
|
+
|
|
41
|
+
- React `>=19`
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { InterfereProvider } from "@interfere/react/provider";
|
|
47
|
+
|
|
48
|
+
function App() {
|
|
49
|
+
return (
|
|
50
|
+
<InterfereProvider>
|
|
51
|
+
<YourApp />
|
|
52
|
+
</InterfereProvider>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
- **Error tracking** — automatic capture of uncaught errors and unhandled rejections
|
|
60
|
+
- **Session replay** — full visual playback of user sessions
|
|
61
|
+
- **Page analytics** — SPA-aware pageviews and UI interaction events
|
|
62
|
+
- **Rage click detection** — surface frustrated user behavior
|
|
63
|
+
- **User identity** — attach user context to sessions
|
|
64
|
+
- **Offline resilient** — events are persisted and delivered in the background
|
|
65
|
+
|
|
66
|
+
## Hooks
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { useInterfere } from "@interfere/react/provider";
|
|
70
|
+
|
|
71
|
+
function MyComponent() {
|
|
72
|
+
const { identity, session } = useInterfere();
|
|
73
|
+
|
|
74
|
+
identity.set({
|
|
75
|
+
identifier: "usr_123",
|
|
76
|
+
email: "jane@example.com",
|
|
77
|
+
name: "Jane",
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const sessionId = session.getId();
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Documentation
|
|
85
|
+
|
|
86
|
+
Visit [interfere.com/docs](https://interfere.com/docs) for the full documentation.
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
MIT
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Component, ErrorInfo, ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/error-boundary.d.ts
|
|
4
|
+
interface ErrorBoundaryProps {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
|
|
7
|
+
onError?: (error: Error, info: ErrorInfo) => void;
|
|
8
|
+
}
|
|
9
|
+
interface ErrorBoundaryState {
|
|
10
|
+
error: Error | null;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Catches render-phase React errors, reports them to the SDK, and renders a
|
|
14
|
+
* fallback. Must be placed inside `<InterfereProvider>` so the client is
|
|
15
|
+
* initialised when `capture` is called.
|
|
16
|
+
*
|
|
17
|
+
* Class component required — React has no hook-based error boundary API.
|
|
18
|
+
*/
|
|
19
|
+
declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
|
20
|
+
state: ErrorBoundaryState;
|
|
21
|
+
static getDerivedStateFromError(error: Error): ErrorBoundaryState;
|
|
22
|
+
componentDidCatch(error: Error, info: ErrorInfo): void;
|
|
23
|
+
private readonly reset;
|
|
24
|
+
render(): ReactNode;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { ErrorBoundary, ErrorBoundaryProps };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-boundary.d.mts","names":[],"sources":["../src/error-boundary.tsx"],"mappings":";;;UASiB,kBAAA;EACf,QAAA,EAAU,SAAA;EACV,QAAA,GAAW,SAAA,KAAc,KAAA,EAAO,KAAA,EAAO,KAAA,iBAAsB,SAAA;EAC7D,OAAA,IAAW,KAAA,EAAO,KAAA,EAAO,IAAA,EAAM,SAAA;AAAA;AAAA,UAGvB,kBAAA;EACR,KAAA,EAAO,KAAA;AAAA;;;;;;;;cAUI,aAAA,SAAsB,SAAA,CACjC,kBAAA,EACA,kBAAA;EAES,KAAA,EAAO,kBAAA;EAAA,OAET,wBAAA,CAAyB,KAAA,EAAO,KAAA,GAAQ,kBAAA;EAItC,iBAAA,CAAkB,KAAA,EAAO,KAAA,EAAO,IAAA,EAAM,SAAA;EAAA,iBAa9B,KAAA;EAIR,MAAA,CAAA,GAAM,SAAA;AAAA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { seen } from "./internal/errors.mjs";
|
|
3
|
+
import { capture } from "./internal/client.mjs";
|
|
4
|
+
import { toExceptions } from "@interfere/types/sdk/errors";
|
|
5
|
+
import { Component } from "react";
|
|
6
|
+
//#region src/error-boundary.tsx
|
|
7
|
+
/**
|
|
8
|
+
* Catches render-phase React errors, reports them to the SDK, and renders a
|
|
9
|
+
* fallback. Must be placed inside `<InterfereProvider>` so the client is
|
|
10
|
+
* initialised when `capture` is called.
|
|
11
|
+
*
|
|
12
|
+
* Class component required — React has no hook-based error boundary API.
|
|
13
|
+
*/
|
|
14
|
+
var ErrorBoundary = class extends Component {
|
|
15
|
+
state = { error: null };
|
|
16
|
+
static getDerivedStateFromError(error) {
|
|
17
|
+
return { error };
|
|
18
|
+
}
|
|
19
|
+
componentDidCatch(error, info) {
|
|
20
|
+
if (seen.has(error)) return;
|
|
21
|
+
seen.add(error);
|
|
22
|
+
capture("error", { exceptions: toExceptions(error, {
|
|
23
|
+
type: "react",
|
|
24
|
+
handled: true
|
|
25
|
+
}) });
|
|
26
|
+
this.props.onError?.(error, info);
|
|
27
|
+
}
|
|
28
|
+
reset = () => {
|
|
29
|
+
this.setState({ error: null });
|
|
30
|
+
};
|
|
31
|
+
render() {
|
|
32
|
+
const { error } = this.state;
|
|
33
|
+
if (error) {
|
|
34
|
+
const { fallback } = this.props;
|
|
35
|
+
if (typeof fallback === "function") return fallback(error, this.reset);
|
|
36
|
+
return fallback ?? null;
|
|
37
|
+
}
|
|
38
|
+
return this.props.children;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
//#endregion
|
|
42
|
+
export { ErrorBoundary };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-boundary.mjs","names":[],"sources":["../src/error-boundary.tsx"],"sourcesContent":["\"use client\";\n\nimport { toExceptions } from \"@interfere/types/sdk/errors\";\n\nimport { Component, type ErrorInfo, type ReactNode } from \"react\";\n\nimport { capture } from \"./internal/client.js\";\nimport { seen } from \"./internal/errors.js\";\n\nexport interface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n onError?: (error: Error, info: ErrorInfo) => void;\n}\n\ninterface ErrorBoundaryState {\n error: Error | null;\n}\n\n/**\n * Catches render-phase React errors, reports them to the SDK, and renders a\n * fallback. Must be placed inside `<InterfereProvider>` so the client is\n * initialised when `capture` is called.\n *\n * Class component required — React has no hook-based error boundary API.\n */\nexport class ErrorBoundary extends Component<\n ErrorBoundaryProps,\n ErrorBoundaryState\n> {\n override state: ErrorBoundaryState = { error: null };\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { error };\n }\n\n override componentDidCatch(error: Error, info: ErrorInfo) {\n if (seen.has(error)) {\n return;\n }\n seen.add(error);\n\n capture(\"error\", {\n exceptions: toExceptions(error, { type: \"react\", handled: true }),\n });\n\n this.props.onError?.(error, info);\n }\n\n private readonly reset = () => {\n this.setState({ error: null });\n };\n\n override render() {\n const { error } = this.state;\n\n if (error) {\n const { fallback } = this.props;\n if (typeof fallback === \"function\") {\n return fallback(error, this.reset);\n }\n return fallback ?? null;\n }\n\n return this.props.children;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AA0BA,IAAa,gBAAb,cAAmC,UAGjC;CACA,QAAqC,EAAE,OAAO,MAAM;CAEpD,OAAO,yBAAyB,OAAkC;AAChE,SAAO,EAAE,OAAO;;CAGlB,kBAA2B,OAAc,MAAiB;AACxD,MAAI,KAAK,IAAI,MAAM,CACjB;AAEF,OAAK,IAAI,MAAM;AAEf,UAAQ,SAAS,EACf,YAAY,aAAa,OAAO;GAAE,MAAM;GAAS,SAAS;GAAM,CAAC,EAClE,CAAC;AAEF,OAAK,MAAM,UAAU,OAAO,KAAK;;CAGnC,cAA+B;AAC7B,OAAK,SAAS,EAAE,OAAO,MAAM,CAAC;;CAGhC,SAAkB;EAChB,MAAM,EAAE,UAAU,KAAK;AAEvB,MAAI,OAAO;GACT,MAAM,EAAE,aAAa,KAAK;AAC1B,OAAI,OAAO,aAAa,WACtB,QAAO,SAAS,OAAO,KAAK,MAAM;AAEpC,UAAO,YAAY;;AAGrB,SAAO,KAAK,MAAM"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PluginOverrides } from "../plugins/lib/loader.mjs";
|
|
2
|
+
import { EnvelopePayload, EventType } from "@interfere/types/sdk/envelope";
|
|
3
|
+
|
|
4
|
+
//#region src/internal/client.d.ts
|
|
5
|
+
interface ClientOptions {
|
|
6
|
+
plugins?: PluginOverrides;
|
|
7
|
+
}
|
|
8
|
+
declare function init(opts?: ClientOptions): void;
|
|
9
|
+
declare function capture<T extends EventType>(type: T, payload: EnvelopePayload<T>): void;
|
|
10
|
+
declare function flush(): void;
|
|
11
|
+
declare function close(): void;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { ClientOptions, capture, close, flush, init };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.mts","names":[],"sources":["../../src/internal/client.ts"],"mappings":";;;;UAiBiB,aAAA;EACf,OAAA,GAAU,eAAA;AAAA;AAAA,iBAQI,IAAA,CAAK,IAAA,GAAM,aAAA;AAAA,iBA0DX,OAAA,WAAkB,SAAA,CAAA,CAChC,IAAA,EAAM,CAAA,EACN,OAAA,EAAS,eAAA,CAAgB,CAAA;AAAA,iBAeX,KAAA,CAAA;AAAA,iBAIA,KAAA,CAAA"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import errorsPlugin from "../plugins/errors.mjs";
|
|
2
|
+
import { createLogger } from "../util/log.mjs";
|
|
3
|
+
import { loadPlugins } from "../plugins/lib/loader.mjs";
|
|
4
|
+
import { bootstrap, session, teardown } from "../tracking/api.mjs";
|
|
5
|
+
import { HttpTransport } from "../transport/http.mjs";
|
|
6
|
+
import { BatchQueue } from "../transport/queue.mjs";
|
|
7
|
+
import { resolveTargets } from "./config.mjs";
|
|
8
|
+
import { collectContext } from "./context.mjs";
|
|
9
|
+
import { buildEnvelope } from "./envelope.mjs";
|
|
10
|
+
import { registerServiceWorker } from "./sw.mjs";
|
|
11
|
+
import { inferRuntime, normalizeEnv } from "@interfere/types/sdk/runtime";
|
|
12
|
+
//#region src/internal/client.ts
|
|
13
|
+
const log = createLogger("client");
|
|
14
|
+
let state = "idle";
|
|
15
|
+
let queue = null;
|
|
16
|
+
let metadata = null;
|
|
17
|
+
let cleanups = [];
|
|
18
|
+
function init(opts = {}) {
|
|
19
|
+
if (state !== "idle") return;
|
|
20
|
+
const buildId = globalThis.__INTERFERE_BUILD_ID__;
|
|
21
|
+
const releaseId = globalThis.__INTERFERE_RELEASE_ID__;
|
|
22
|
+
if (!buildId) {
|
|
23
|
+
log.error("buildId not found — ensure withInterfere() is configured in next.config and instrumentation-client.ts exists in your project root.");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const targets = resolveTargets();
|
|
27
|
+
bootstrap(targets.session, opts.plugins);
|
|
28
|
+
log.info("target: %s", targets.ingest.url);
|
|
29
|
+
metadata = {
|
|
30
|
+
context: collectContext(),
|
|
31
|
+
environment: normalizeEnv(typeof process !== "undefined" ? process.env.NODE_ENV : void 0),
|
|
32
|
+
runtime: inferRuntime(),
|
|
33
|
+
buildId,
|
|
34
|
+
releaseId: releaseId ?? null
|
|
35
|
+
};
|
|
36
|
+
registerServiceWorker();
|
|
37
|
+
queue = new BatchQueue({ transport: new HttpTransport(targets.ingest) });
|
|
38
|
+
queue.start();
|
|
39
|
+
const pluginCtx = {
|
|
40
|
+
capture: (type, payload) => capture(type, payload),
|
|
41
|
+
getSessionId: () => session.getId() ?? ""
|
|
42
|
+
};
|
|
43
|
+
const errorCleanup = errorsPlugin.setup(pluginCtx);
|
|
44
|
+
cleanups = errorCleanup ? [errorCleanup] : [];
|
|
45
|
+
state = "ready";
|
|
46
|
+
loadPlugins({
|
|
47
|
+
...opts.plugins,
|
|
48
|
+
errors: false
|
|
49
|
+
}, pluginCtx).then((c) => {
|
|
50
|
+
cleanups.push(...c);
|
|
51
|
+
}).catch(() => {
|
|
52
|
+
log.warn("non-critical plugin loading failed");
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function capture(type, payload) {
|
|
56
|
+
try {
|
|
57
|
+
const sessionId = session.getId();
|
|
58
|
+
if (state !== "ready" || !sessionId || !queue || !metadata) return;
|
|
59
|
+
queue.enqueue(buildEnvelope(type, payload, sessionId, metadata));
|
|
60
|
+
} catch (err) {
|
|
61
|
+
log.warn("capture failed", err);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function flush() {
|
|
65
|
+
queue?.flush();
|
|
66
|
+
}
|
|
67
|
+
function close() {
|
|
68
|
+
if (state === "closed") return;
|
|
69
|
+
state = "closed";
|
|
70
|
+
for (const cleanup of cleanups) try {
|
|
71
|
+
cleanup();
|
|
72
|
+
} catch {}
|
|
73
|
+
cleanups = [];
|
|
74
|
+
teardown();
|
|
75
|
+
queue?.dispose();
|
|
76
|
+
queue = null;
|
|
77
|
+
metadata = null;
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
export { capture, close, flush, init };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.mjs","names":[],"sources":["../../src/internal/client.ts"],"sourcesContent":["import type { EnvelopePayload, EventType } from \"@interfere/types/sdk/envelope\";\nimport { inferRuntime, normalizeEnv } from \"@interfere/types/sdk/runtime\";\n\nimport errorsPlugin from \"../plugins/errors.js\";\nimport { loadPlugins, type PluginOverrides } from \"../plugins/lib/loader.js\";\nimport type { PluginCleanup, PluginContext } from \"../plugins/lib/types.js\";\nimport { bootstrap, session, teardown } from \"../tracking/api.js\";\nimport { HttpTransport } from \"../transport/http.js\";\nimport { BatchQueue } from \"../transport/queue.js\";\nimport { createLogger } from \"../util/log.js\";\nimport { resolveTargets } from \"./config.js\";\nimport { collectContext } from \"./context.js\";\nimport { buildEnvelope, type EnvelopeMetadata } from \"./envelope.js\";\nimport { registerServiceWorker } from \"./sw.js\";\n\nconst log = createLogger(\"client\");\n\nexport interface ClientOptions {\n plugins?: PluginOverrides;\n}\n\nlet state: \"idle\" | \"ready\" | \"closed\" = \"idle\";\nlet queue: BatchQueue | null = null;\nlet metadata: EnvelopeMetadata | null = null;\nlet cleanups: PluginCleanup[] = [];\n\nexport function init(opts: ClientOptions = {}): void {\n if (state !== \"idle\") {\n return;\n }\n\n const buildId = (globalThis as Record<string, unknown>)\n .__INTERFERE_BUILD_ID__ as string | undefined;\n\n const releaseId = (globalThis as Record<string, unknown>)\n .__INTERFERE_RELEASE_ID__ as string | null | undefined;\n\n if (!buildId) {\n log.error(\n \"buildId not found — ensure withInterfere() is configured in \" +\n \"next.config and instrumentation-client.ts exists in your project root.\"\n );\n return;\n }\n\n const targets = resolveTargets();\n bootstrap(targets.session, opts.plugins);\n\n log.info(\"target: %s\", targets.ingest.url);\n\n metadata = {\n context: collectContext(),\n environment: normalizeEnv(\n typeof process !== \"undefined\" ? process.env.NODE_ENV : undefined\n ),\n runtime: inferRuntime(),\n buildId,\n releaseId: releaseId ?? null,\n };\n\n registerServiceWorker();\n\n const transport = new HttpTransport(targets.ingest);\n queue = new BatchQueue({ transport });\n queue.start();\n\n const pluginCtx: PluginContext = {\n capture: (type, payload) => capture(type, payload),\n getSessionId: () => session.getId() ?? \"\",\n };\n\n const errorCleanup = errorsPlugin.setup(pluginCtx);\n cleanups = errorCleanup ? [errorCleanup] : [];\n state = \"ready\";\n\n loadPlugins({ ...opts.plugins, errors: false }, pluginCtx)\n .then((c) => {\n cleanups.push(...c);\n })\n .catch(() => {\n log.warn(\"non-critical plugin loading failed\");\n });\n}\n\nexport function capture<T extends EventType>(\n type: T,\n payload: EnvelopePayload<T>\n): void {\n try {\n const sessionId = session.getId();\n\n if (state !== \"ready\" || !sessionId || !queue || !metadata) {\n return;\n }\n\n queue.enqueue(buildEnvelope(type, payload, sessionId, metadata));\n } catch (err) {\n log.warn(\"capture failed\", err);\n }\n}\n\nexport function flush(): void {\n queue?.flush();\n}\n\nexport function close(): void {\n if (state === \"closed\") {\n return;\n }\n state = \"closed\";\n\n for (const cleanup of cleanups) {\n try {\n cleanup();\n } catch {\n /* best-effort */\n }\n }\n cleanups = [];\n teardown();\n\n queue?.dispose();\n queue = null;\n metadata = null;\n}\n"],"mappings":";;;;;;;;;;;;AAeA,MAAM,MAAM,aAAa,SAAS;AAMlC,IAAI,QAAqC;AACzC,IAAI,QAA2B;AAC/B,IAAI,WAAoC;AACxC,IAAI,WAA4B,EAAE;AAElC,SAAgB,KAAK,OAAsB,EAAE,EAAQ;AACnD,KAAI,UAAU,OACZ;CAGF,MAAM,UAAW,WACd;CAEH,MAAM,YAAa,WAChB;AAEH,KAAI,CAAC,SAAS;AACZ,MAAI,MACF,qIAED;AACD;;CAGF,MAAM,UAAU,gBAAgB;AAChC,WAAU,QAAQ,SAAS,KAAK,QAAQ;AAExC,KAAI,KAAK,cAAc,QAAQ,OAAO,IAAI;AAE1C,YAAW;EACT,SAAS,gBAAgB;EACzB,aAAa,aACX,OAAO,YAAY,cAAc,QAAQ,IAAI,WAAW,KAAA,EACzD;EACD,SAAS,cAAc;EACvB;EACA,WAAW,aAAa;EACzB;AAED,wBAAuB;AAGvB,SAAQ,IAAI,WAAW,EAAE,WADP,IAAI,cAAc,QAAQ,OAAO,EACf,CAAC;AACrC,OAAM,OAAO;CAEb,MAAM,YAA2B;EAC/B,UAAU,MAAM,YAAY,QAAQ,MAAM,QAAQ;EAClD,oBAAoB,QAAQ,OAAO,IAAI;EACxC;CAED,MAAM,eAAe,aAAa,MAAM,UAAU;AAClD,YAAW,eAAe,CAAC,aAAa,GAAG,EAAE;AAC7C,SAAQ;AAER,aAAY;EAAE,GAAG,KAAK;EAAS,QAAQ;EAAO,EAAE,UAAU,CACvD,MAAM,MAAM;AACX,WAAS,KAAK,GAAG,EAAE;GACnB,CACD,YAAY;AACX,MAAI,KAAK,qCAAqC;GAC9C;;AAGN,SAAgB,QACd,MACA,SACM;AACN,KAAI;EACF,MAAM,YAAY,QAAQ,OAAO;AAEjC,MAAI,UAAU,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC,SAChD;AAGF,QAAM,QAAQ,cAAc,MAAM,SAAS,WAAW,SAAS,CAAC;UACzD,KAAK;AACZ,MAAI,KAAK,kBAAkB,IAAI;;;AAInC,SAAgB,QAAc;AAC5B,QAAO,OAAO;;AAGhB,SAAgB,QAAc;AAC5B,KAAI,UAAU,SACZ;AAEF,SAAQ;AAER,MAAK,MAAM,WAAW,SACpB,KAAI;AACF,WAAS;SACH;AAIV,YAAW,EAAE;AACb,WAAU;AAEV,QAAO,SAAS;AAChB,SAAQ;AACR,YAAW"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.mts","names":[],"sources":["../../src/internal/config.ts"],"mappings":";;;iBAcgB,cAAA,CAAA;EACd,MAAA,EAAQ,YAAA;EACR,OAAA,EAAS,YAAA;AAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { API_PATHS, API_URL } from "@interfere/constants/api";
|
|
2
|
+
//#region src/internal/config.ts
|
|
3
|
+
const DEFAULT_PROXY_URL = "/api/interfere";
|
|
4
|
+
const DEFAULT_SESSION_PATH = "/v1/session";
|
|
5
|
+
function resolvePublicKey() {
|
|
6
|
+
if (typeof process === "undefined") return;
|
|
7
|
+
return process.env.INTERFERE_PUBLIC_KEY ?? void 0;
|
|
8
|
+
}
|
|
9
|
+
function resolveTargets() {
|
|
10
|
+
const publicKey = resolvePublicKey();
|
|
11
|
+
const headers = new Headers({ "content-type": "application/json" });
|
|
12
|
+
if (publicKey) headers.set("x-interfere-pub-token", publicKey);
|
|
13
|
+
const baseUrl = publicKey ? API_URL : DEFAULT_PROXY_URL;
|
|
14
|
+
const sessionPath = API_PATHS.SESSION ?? DEFAULT_SESSION_PATH;
|
|
15
|
+
return {
|
|
16
|
+
ingest: {
|
|
17
|
+
url: `${baseUrl}${API_PATHS.INGEST}`,
|
|
18
|
+
headers
|
|
19
|
+
},
|
|
20
|
+
session: {
|
|
21
|
+
url: `${baseUrl}${sessionPath}`,
|
|
22
|
+
headers
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { resolveTargets };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.mjs","names":[],"sources":["../../src/internal/config.ts"],"sourcesContent":["import { API_PATHS, API_URL } from \"@interfere/constants/api\";\n\nimport type { IngestTarget } from \"../transport/http.js\";\n\nconst DEFAULT_PROXY_URL = \"/api/interfere\";\nconst DEFAULT_SESSION_PATH = \"/v1/session\";\n\nfunction resolvePublicKey(): string | undefined {\n if (typeof process === \"undefined\") {\n return undefined;\n }\n return process.env.INTERFERE_PUBLIC_KEY ?? undefined;\n}\n\nexport function resolveTargets(): {\n ingest: IngestTarget;\n session: IngestTarget;\n} {\n const publicKey = resolvePublicKey();\n const headers = new Headers({ \"content-type\": \"application/json\" });\n if (publicKey) {\n headers.set(\"x-interfere-pub-token\", publicKey);\n }\n\n const baseUrl = publicKey ? API_URL : DEFAULT_PROXY_URL;\n const sessionPath =\n (API_PATHS as { SESSION?: string }).SESSION ?? DEFAULT_SESSION_PATH;\n\n return {\n ingest: {\n url: `${baseUrl}${API_PATHS.INGEST}`,\n headers,\n },\n session: {\n url: `${baseUrl}${sessionPath}`,\n headers,\n },\n };\n}\n"],"mappings":";;AAIA,MAAM,oBAAoB;AAC1B,MAAM,uBAAuB;AAE7B,SAAS,mBAAuC;AAC9C,KAAI,OAAO,YAAY,YACrB;AAEF,QAAO,QAAQ,IAAI,wBAAwB,KAAA;;AAG7C,SAAgB,iBAGd;CACA,MAAM,YAAY,kBAAkB;CACpC,MAAM,UAAU,IAAI,QAAQ,EAAE,gBAAgB,oBAAoB,CAAC;AACnE,KAAI,UACF,SAAQ,IAAI,yBAAyB,UAAU;CAGjD,MAAM,UAAU,YAAY,UAAU;CACtC,MAAM,cACH,UAAmC,WAAW;AAEjD,QAAO;EACL,QAAQ;GACN,KAAK,GAAG,UAAU,UAAU;GAC5B;GACD;EACD,SAAS;GACP,KAAK,GAAG,UAAU;GAClB;GACD;EACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.mts","names":[],"sources":["../../src/internal/context.ts"],"mappings":";;;iBAwCgB,cAAA,CAAA,GAAkB,cAAA"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { UAParser } from "@ua-parser-js/pro-enterprise";
|
|
2
|
+
//#region src/internal/context.ts
|
|
3
|
+
function getDeviceMetadata() {
|
|
4
|
+
if (typeof navigator === "undefined") return null;
|
|
5
|
+
return UAParser(navigator.userAgent) ?? null;
|
|
6
|
+
}
|
|
7
|
+
function getBrowserMetadata() {
|
|
8
|
+
if ([
|
|
9
|
+
typeof navigator,
|
|
10
|
+
typeof screen,
|
|
11
|
+
typeof globalThis
|
|
12
|
+
].some((x) => x === "undefined")) return null;
|
|
13
|
+
const { language } = navigator;
|
|
14
|
+
return {
|
|
15
|
+
language,
|
|
16
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
17
|
+
display: { screen: {
|
|
18
|
+
height: screen.availHeight,
|
|
19
|
+
width: screen.availWidth,
|
|
20
|
+
orientation: screen.orientation?.type
|
|
21
|
+
} }
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function collectContext() {
|
|
25
|
+
return {
|
|
26
|
+
runtime: "browser",
|
|
27
|
+
browser: getBrowserMetadata(),
|
|
28
|
+
device: getDeviceMetadata()
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { collectContext };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.mjs","names":[],"sources":["../../src/internal/context.ts"],"sourcesContent":["import type {\n BrowserContext,\n BrowserMetadata,\n DeviceMetadata,\n} from \"@interfere/types/sdk/plugins/context/browser\";\n\nimport { UAParser } from \"@ua-parser-js/pro-enterprise\";\n\nfunction getDeviceMetadata(): DeviceMetadata | null {\n if (typeof navigator === \"undefined\") {\n return null;\n }\n\n return UAParser(navigator.userAgent) ?? null;\n}\n\nfunction getBrowserMetadata(): BrowserMetadata | null {\n if (\n [typeof navigator, typeof screen, typeof globalThis].some(\n (x) => x === \"undefined\"\n )\n ) {\n return null;\n }\n\n const { language } = navigator;\n\n return {\n language,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n display: {\n screen: {\n height: screen.availHeight,\n width: screen.availWidth,\n orientation: screen.orientation?.type,\n },\n },\n };\n}\n\nexport function collectContext(): BrowserContext {\n return {\n runtime: \"browser\",\n browser: getBrowserMetadata(),\n device: getDeviceMetadata(),\n };\n}\n"],"mappings":";;AAQA,SAAS,oBAA2C;AAClD,KAAI,OAAO,cAAc,YACvB,QAAO;AAGT,QAAO,SAAS,UAAU,UAAU,IAAI;;AAG1C,SAAS,qBAA6C;AACpD,KACE;EAAC,OAAO;EAAW,OAAO;EAAQ,OAAO;EAAW,CAAC,MAClD,MAAM,MAAM,YACd,CAED,QAAO;CAGT,MAAM,EAAE,aAAa;AAErB,QAAO;EACL;EACA,UAAU,KAAK,gBAAgB,CAAC,iBAAiB,CAAC;EAClD,SAAS,EACP,QAAQ;GACN,QAAQ,OAAO;GACf,OAAO,OAAO;GACd,aAAa,OAAO,aAAa;GAClC,EACF;EACF;;AAGH,SAAgB,iBAAiC;AAC/C,QAAO;EACL,SAAS;EACT,SAAS,oBAAoB;EAC7B,QAAQ,mBAAmB;EAC5B"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Env, Runtime } from "@interfere/types/sdk/runtime";
|
|
2
|
+
import { Envelope, EnvelopeContext, EnvelopePayload, EventType } from "@interfere/types/sdk/envelope";
|
|
3
|
+
|
|
4
|
+
//#region src/internal/envelope.d.ts
|
|
5
|
+
interface EnvelopeMetadata {
|
|
6
|
+
buildId: string;
|
|
7
|
+
context: EnvelopeContext;
|
|
8
|
+
environment: Env;
|
|
9
|
+
releaseId: string | null;
|
|
10
|
+
runtime: Runtime;
|
|
11
|
+
}
|
|
12
|
+
declare function buildEnvelope<T extends EventType>(type: T, payload: EnvelopePayload<T>, sessionId: string, metadata: EnvelopeMetadata): Envelope<T>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { EnvelopeMetadata, buildEnvelope };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.d.mts","names":[],"sources":["../../src/internal/envelope.ts"],"mappings":";;;;UAUiB,gBAAA;EACf,OAAA;EACA,OAAA,EAAS,eAAA;EACT,WAAA,EAAa,GAAA;EACb,SAAA;EACA,OAAA,EAAS,OAAA;AAAA;AAAA,iBAGK,aAAA,WAAwB,SAAA,CAAA,CACtC,IAAA,EAAM,CAAA,EACN,OAAA,EAAS,eAAA,CAAgB,CAAA,GACzB,SAAA,UACA,QAAA,EAAU,gBAAA,GACT,QAAA,CAAS,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { v7 } from "uuid";
|
|
2
|
+
//#region src/internal/envelope.ts
|
|
3
|
+
function buildEnvelope(type, payload, sessionId, metadata) {
|
|
4
|
+
return {
|
|
5
|
+
uuid: v7(),
|
|
6
|
+
v: 0,
|
|
7
|
+
type,
|
|
8
|
+
payload,
|
|
9
|
+
context: metadata.context,
|
|
10
|
+
runtime: metadata.runtime,
|
|
11
|
+
environment: metadata.environment,
|
|
12
|
+
buildId: metadata.buildId,
|
|
13
|
+
releaseId: metadata.releaseId,
|
|
14
|
+
clientTs: Date.now(),
|
|
15
|
+
sessionId,
|
|
16
|
+
sessionSource: "client"
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { buildEnvelope };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.mjs","names":["uuidv7"],"sources":["../../src/internal/envelope.ts"],"sourcesContent":["import type {\n Envelope,\n EnvelopeContext,\n EnvelopePayload,\n EventType,\n} from \"@interfere/types/sdk/envelope\";\nimport type { Env, Runtime } from \"@interfere/types/sdk/runtime\";\n\nimport { v7 as uuidv7 } from \"uuid\";\n\nexport interface EnvelopeMetadata {\n buildId: string;\n context: EnvelopeContext;\n environment: Env;\n releaseId: string | null;\n runtime: Runtime;\n}\n\nexport function buildEnvelope<T extends EventType>(\n type: T,\n payload: EnvelopePayload<T>,\n sessionId: string,\n metadata: EnvelopeMetadata\n): Envelope<T> {\n return {\n uuid: uuidv7(),\n v: 0 as const,\n type,\n payload,\n context: metadata.context,\n runtime: metadata.runtime,\n environment: metadata.environment,\n buildId: metadata.buildId,\n releaseId: metadata.releaseId,\n clientTs: Date.now(),\n sessionId,\n sessionSource: \"client\" as const,\n } as Envelope<T>;\n}\n"],"mappings":";;AAkBA,SAAgB,cACd,MACA,SACA,WACA,UACa;AACb,QAAO;EACL,MAAMA,IAAQ;EACd,GAAG;EACH;EACA;EACA,SAAS,SAAS;EAClB,SAAS,SAAS;EAClB,aAAa,SAAS;EACtB,SAAS,SAAS;EAClB,WAAW,SAAS;EACpB,UAAU,KAAK,KAAK;EACpB;EACA,eAAe;EAChB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.mts","names":[],"sources":["../../src/internal/errors.ts"],"mappings":";cAAa,IAAA,EAAI,OAAA,CAAA,KAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.mjs","names":[],"sources":["../../src/internal/errors.ts"],"sourcesContent":["export const seen = new WeakSet<Error>();\n"],"mappings":";AAAA,MAAa,uBAAO,IAAI,SAAgB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sw.d.mts","names":[],"sources":["../../src/internal/sw.ts"],"mappings":";iBAMgB,qBAAA,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createLogger } from "../util/log.mjs";
|
|
2
|
+
//#region src/internal/sw.ts
|
|
3
|
+
const log = createLogger("sw");
|
|
4
|
+
const SW_PATH = "/api/interfere/sw";
|
|
5
|
+
function registerServiceWorker() {
|
|
6
|
+
if (typeof navigator === "undefined" || !("serviceWorker" in navigator)) return;
|
|
7
|
+
navigator.serviceWorker.register(SW_PATH, { scope: "/" }).then(() => log.debug("registered")).catch(() => log.warn("registration failed, using direct fetch"));
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { registerServiceWorker };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sw.mjs","names":[],"sources":["../../src/internal/sw.ts"],"sourcesContent":["import { createLogger } from \"../util/log.js\";\n\nconst log = createLogger(\"sw\");\n\nconst SW_PATH = \"/api/interfere/sw\";\n\nexport function registerServiceWorker(): void {\n if (typeof navigator === \"undefined\" || !(\"serviceWorker\" in navigator)) {\n return;\n }\n\n navigator.serviceWorker\n .register(SW_PATH, { scope: \"/\" })\n .then(() => log.debug(\"registered\"))\n .catch(() => log.warn(\"registration failed, using direct fetch\"));\n}\n"],"mappings":";;AAEA,MAAM,MAAM,aAAa,KAAK;AAE9B,MAAM,UAAU;AAEhB,SAAgB,wBAA8B;AAC5C,KAAI,OAAO,cAAc,eAAe,EAAE,mBAAmB,WAC3D;AAGF,WAAU,cACP,SAAS,SAAS,EAAE,OAAO,KAAK,CAAC,CACjC,WAAW,IAAI,MAAM,aAAa,CAAC,CACnC,YAAY,IAAI,KAAK,0CAA0C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.mts","names":[],"sources":["../../src/plugins/errors.ts"],"mappings":";;;cA2Ba,YAAA,EAAc,MAAA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { seen } from "../internal/errors.mjs";
|
|
2
|
+
import { toExceptions } from "@interfere/types/sdk/errors";
|
|
3
|
+
//#region src/plugins/errors.ts
|
|
4
|
+
let capturing = false;
|
|
5
|
+
function capture(ctx, opts) {
|
|
6
|
+
if (capturing || seen.has(opts.error)) return;
|
|
7
|
+
seen.add(opts.error);
|
|
8
|
+
capturing = true;
|
|
9
|
+
try {
|
|
10
|
+
ctx.capture("error", { exceptions: toExceptions(opts.error, opts.mechanism) });
|
|
11
|
+
} finally {
|
|
12
|
+
capturing = false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const errorsPlugin = {
|
|
16
|
+
name: "errors",
|
|
17
|
+
setup(ctx) {
|
|
18
|
+
const originalOnError = globalThis.onerror;
|
|
19
|
+
const originalConsoleError = globalThis.console.error;
|
|
20
|
+
globalThis.onerror = (msg, source, line, col, error) => {
|
|
21
|
+
if (error instanceof Error) capture(ctx, {
|
|
22
|
+
error,
|
|
23
|
+
mechanism: {
|
|
24
|
+
type: "onerror",
|
|
25
|
+
handled: false
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
if (typeof originalOnError === "function") return originalOnError.call(globalThis, msg, source, line, col, error);
|
|
29
|
+
return false;
|
|
30
|
+
};
|
|
31
|
+
const onUnhandledRejection = (event) => {
|
|
32
|
+
if (event.reason instanceof Error) capture(ctx, {
|
|
33
|
+
error: event.reason,
|
|
34
|
+
mechanism: {
|
|
35
|
+
type: "unhandledrejection",
|
|
36
|
+
handled: false
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
globalThis.addEventListener("unhandledrejection", onUnhandledRejection);
|
|
41
|
+
globalThis.console.error = (...args) => {
|
|
42
|
+
originalConsoleError.apply(globalThis.console, args);
|
|
43
|
+
if (args[0] instanceof Error) capture(ctx, {
|
|
44
|
+
error: args[0],
|
|
45
|
+
mechanism: {
|
|
46
|
+
type: "console.error",
|
|
47
|
+
handled: true
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
return () => {
|
|
52
|
+
globalThis.onerror = originalOnError;
|
|
53
|
+
globalThis.removeEventListener("unhandledrejection", onUnhandledRejection);
|
|
54
|
+
globalThis.console.error = originalConsoleError;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
//#endregion
|
|
59
|
+
export { errorsPlugin as default, errorsPlugin };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.mjs","names":[],"sources":["../../src/plugins/errors.ts"],"sourcesContent":["import { toExceptions } from \"@interfere/types/sdk/errors\";\nimport type { ErrorMechanism } from \"@interfere/types/sdk/plugins/payload/errors\";\n\nimport { seen } from \"../internal/errors.js\";\nimport type { Plugin, PluginContext } from \"./lib/types.js\";\n\nlet capturing = false;\n\nfunction capture(\n ctx: PluginContext,\n opts: { error: Error; mechanism: ErrorMechanism }\n) {\n if (capturing || seen.has(opts.error)) {\n return;\n }\n\n seen.add(opts.error);\n capturing = true;\n try {\n ctx.capture(\"error\", {\n exceptions: toExceptions(opts.error, opts.mechanism),\n });\n } finally {\n capturing = false;\n }\n}\n\nexport const errorsPlugin: Plugin = {\n name: \"errors\",\n\n setup(ctx) {\n const originalOnError = globalThis.onerror;\n const originalConsoleError = globalThis.console.error;\n\n globalThis.onerror = (msg, source, line, col, error) => {\n if (error instanceof Error) {\n capture(ctx, {\n error,\n mechanism: { type: \"onerror\", handled: false },\n });\n }\n if (typeof originalOnError === \"function\") {\n return originalOnError.call(globalThis, msg, source, line, col, error);\n }\n return false;\n };\n\n const onUnhandledRejection = (event: PromiseRejectionEvent) => {\n if (event.reason instanceof Error) {\n capture(ctx, {\n error: event.reason,\n mechanism: { type: \"unhandledrejection\", handled: false },\n });\n }\n };\n globalThis.addEventListener(\"unhandledrejection\", onUnhandledRejection);\n\n globalThis.console.error = (...args: unknown[]) => {\n originalConsoleError.apply(globalThis.console, args);\n if (args[0] instanceof Error) {\n capture(ctx, {\n error: args[0],\n mechanism: { type: \"console.error\", handled: true },\n });\n }\n };\n\n return () => {\n globalThis.onerror = originalOnError;\n globalThis.removeEventListener(\n \"unhandledrejection\",\n onUnhandledRejection\n );\n globalThis.console.error = originalConsoleError;\n };\n },\n};\n\nexport default errorsPlugin;\n"],"mappings":";;;AAMA,IAAI,YAAY;AAEhB,SAAS,QACP,KACA,MACA;AACA,KAAI,aAAa,KAAK,IAAI,KAAK,MAAM,CACnC;AAGF,MAAK,IAAI,KAAK,MAAM;AACpB,aAAY;AACZ,KAAI;AACF,MAAI,QAAQ,SAAS,EACnB,YAAY,aAAa,KAAK,OAAO,KAAK,UAAU,EACrD,CAAC;WACM;AACR,cAAY;;;AAIhB,MAAa,eAAuB;CAClC,MAAM;CAEN,MAAM,KAAK;EACT,MAAM,kBAAkB,WAAW;EACnC,MAAM,uBAAuB,WAAW,QAAQ;AAEhD,aAAW,WAAW,KAAK,QAAQ,MAAM,KAAK,UAAU;AACtD,OAAI,iBAAiB,MACnB,SAAQ,KAAK;IACX;IACA,WAAW;KAAE,MAAM;KAAW,SAAS;KAAO;IAC/C,CAAC;AAEJ,OAAI,OAAO,oBAAoB,WAC7B,QAAO,gBAAgB,KAAK,YAAY,KAAK,QAAQ,MAAM,KAAK,MAAM;AAExE,UAAO;;EAGT,MAAM,wBAAwB,UAAiC;AAC7D,OAAI,MAAM,kBAAkB,MAC1B,SAAQ,KAAK;IACX,OAAO,MAAM;IACb,WAAW;KAAE,MAAM;KAAsB,SAAS;KAAO;IAC1D,CAAC;;AAGN,aAAW,iBAAiB,sBAAsB,qBAAqB;AAEvE,aAAW,QAAQ,SAAS,GAAG,SAAoB;AACjD,wBAAqB,MAAM,WAAW,SAAS,KAAK;AACpD,OAAI,KAAK,cAAc,MACrB,SAAQ,KAAK;IACX,OAAO,KAAK;IACZ,WAAW;KAAE,MAAM;KAAiB,SAAS;KAAM;IACpD,CAAC;;AAIN,eAAa;AACX,cAAW,UAAU;AACrB,cAAW,oBACT,sBACA,qBACD;AACD,cAAW,QAAQ,QAAQ;;;CAGhC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PluginCleanup, PluginContext } from "./types.mjs";
|
|
2
|
+
import { PluginKey } from "@interfere/types/sdk/plugins/manifest";
|
|
3
|
+
|
|
4
|
+
//#region src/plugins/lib/loader.d.ts
|
|
5
|
+
type PluginOverrides = Partial<Record<PluginKey, boolean>>;
|
|
6
|
+
declare function resolveFeatures(overrides?: PluginOverrides): Record<PluginKey, boolean>;
|
|
7
|
+
declare function loadPlugins(overrides: PluginOverrides | undefined, context: PluginContext): Promise<PluginCleanup[]>;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { PluginOverrides, loadPlugins, resolveFeatures };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.mts","names":[],"sources":["../../../src/plugins/lib/loader.ts"],"mappings":";;;;KAuBY,eAAA,GAAkB,OAAA,CAAQ,MAAA,CAAO,SAAA;AAAA,iBAE7B,eAAA,CACd,SAAA,GAAY,eAAA,GACX,MAAA,CAAO,SAAA;AAAA,iBAUY,WAAA,CACpB,SAAA,EAAW,eAAA,cACX,OAAA,EAAS,aAAA,GACR,OAAA,CAAQ,aAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createLogger } from "../../util/log.mjs";
|
|
2
|
+
import { PLUGIN_MANIFEST } from "@interfere/types/sdk/plugins/manifest";
|
|
3
|
+
//#region src/plugins/lib/loader.ts
|
|
4
|
+
const log = createLogger("plugins");
|
|
5
|
+
const LOADERS = {
|
|
6
|
+
errors: () => import("../errors.mjs"),
|
|
7
|
+
pageEvents: () => import("../pages.mjs"),
|
|
8
|
+
rageClick: () => import("../rage-clicks.mjs"),
|
|
9
|
+
replay: () => import("../replay.mjs")
|
|
10
|
+
};
|
|
11
|
+
const DEFAULTS = Object.fromEntries(PLUGIN_MANIFEST.map((p) => [p.name, p.defaultEnabled]));
|
|
12
|
+
function resolveFeatures(overrides) {
|
|
13
|
+
return {
|
|
14
|
+
...DEFAULTS,
|
|
15
|
+
...overrides
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function resolvePlugin(mod) {
|
|
19
|
+
return "default" in mod && typeof mod.default.setup === "function" ? mod.default : mod;
|
|
20
|
+
}
|
|
21
|
+
async function loadPlugins(overrides, context) {
|
|
22
|
+
const resolved = {
|
|
23
|
+
...DEFAULTS,
|
|
24
|
+
...overrides
|
|
25
|
+
};
|
|
26
|
+
const entries = Object.entries(resolved).filter(([key, enabled]) => enabled && key in LOADERS);
|
|
27
|
+
const modules = await Promise.all(entries.map(async ([key]) => {
|
|
28
|
+
const loader = LOADERS[key];
|
|
29
|
+
if (!loader) return null;
|
|
30
|
+
try {
|
|
31
|
+
return await loader();
|
|
32
|
+
} catch {
|
|
33
|
+
log.error("failed to load plugin %s", key);
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}));
|
|
37
|
+
const cleanups = [];
|
|
38
|
+
for (const [i, mod] of modules.entries()) {
|
|
39
|
+
if (!mod) continue;
|
|
40
|
+
const cleanup = resolvePlugin(mod).setup(context);
|
|
41
|
+
if (typeof cleanup === "function") cleanups.push(cleanup);
|
|
42
|
+
log.debug("loaded %s", entries[i]?.[0]);
|
|
43
|
+
}
|
|
44
|
+
return cleanups;
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
export { loadPlugins, resolveFeatures };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.mjs","names":[],"sources":["../../../src/plugins/lib/loader.ts"],"sourcesContent":["import {\n PLUGIN_MANIFEST,\n type PluginKey,\n} from \"@interfere/types/sdk/plugins/manifest\";\n\nimport { createLogger } from \"../../util/log.js\";\nimport type { Plugin, PluginCleanup, PluginContext } from \"./types.js\";\n\nconst log = createLogger(\"plugins\");\n\ntype PluginLoader = () => Promise<{ default: Plugin } | Plugin>;\n\nconst LOADERS: Partial<Record<PluginKey, PluginLoader>> = {\n errors: () => import(\"../errors.js\"),\n pageEvents: () => import(\"../pages.js\"),\n rageClick: () => import(\"../rage-clicks.js\"),\n replay: () => import(\"../replay.js\"),\n};\n\nconst DEFAULTS: Record<PluginKey, boolean> = Object.fromEntries(\n PLUGIN_MANIFEST.map((p) => [p.name, p.defaultEnabled])\n) as Record<PluginKey, boolean>;\n\nexport type PluginOverrides = Partial<Record<PluginKey, boolean>>;\n\nexport function resolveFeatures(\n overrides?: PluginOverrides\n): Record<PluginKey, boolean> {\n return { ...DEFAULTS, ...overrides };\n}\n\nfunction resolvePlugin(mod: { default: Plugin } | Plugin): Plugin {\n return \"default\" in mod && typeof (mod.default as Plugin).setup === \"function\"\n ? mod.default\n : (mod as Plugin);\n}\n\nexport async function loadPlugins(\n overrides: PluginOverrides | undefined,\n context: PluginContext\n): Promise<PluginCleanup[]> {\n const resolved = { ...DEFAULTS, ...overrides };\n const entries = (Object.entries(resolved) as [PluginKey, boolean][]).filter(\n ([key, enabled]) => enabled && key in LOADERS\n );\n\n const modules = await Promise.all(\n entries.map(async ([key]) => {\n const loader = LOADERS[key];\n if (!loader) {\n return null;\n }\n try {\n return await loader();\n } catch {\n log.error(\"failed to load plugin %s\", key);\n return null;\n }\n })\n );\n\n const cleanups: PluginCleanup[] = [];\n\n for (const [i, mod] of modules.entries()) {\n if (!mod) {\n continue;\n }\n const plugin = resolvePlugin(mod);\n const cleanup = plugin.setup(context);\n if (typeof cleanup === \"function\") {\n cleanups.push(cleanup);\n }\n log.debug(\"loaded %s\", entries[i]?.[0]);\n }\n\n return cleanups;\n}\n"],"mappings":";;;AAQA,MAAM,MAAM,aAAa,UAAU;AAInC,MAAM,UAAoD;CACxD,cAAc,OAAO;CACrB,kBAAkB,OAAO;CACzB,iBAAiB,OAAO;CACxB,cAAc,OAAO;CACtB;AAED,MAAM,WAAuC,OAAO,YAClD,gBAAgB,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,CACvD;AAID,SAAgB,gBACd,WAC4B;AAC5B,QAAO;EAAE,GAAG;EAAU,GAAG;EAAW;;AAGtC,SAAS,cAAc,KAA2C;AAChE,QAAO,aAAa,OAAO,OAAQ,IAAI,QAAmB,UAAU,aAChE,IAAI,UACH;;AAGP,eAAsB,YACpB,WACA,SAC0B;CAC1B,MAAM,WAAW;EAAE,GAAG;EAAU,GAAG;EAAW;CAC9C,MAAM,UAAW,OAAO,QAAQ,SAAS,CAA4B,QAClE,CAAC,KAAK,aAAa,WAAW,OAAO,QACvC;CAED,MAAM,UAAU,MAAM,QAAQ,IAC5B,QAAQ,IAAI,OAAO,CAAC,SAAS;EAC3B,MAAM,SAAS,QAAQ;AACvB,MAAI,CAAC,OACH,QAAO;AAET,MAAI;AACF,UAAO,MAAM,QAAQ;UACf;AACN,OAAI,MAAM,4BAA4B,IAAI;AAC1C,UAAO;;GAET,CACH;CAED,MAAM,WAA4B,EAAE;AAEpC,MAAK,MAAM,CAAC,GAAG,QAAQ,QAAQ,SAAS,EAAE;AACxC,MAAI,CAAC,IACH;EAGF,MAAM,UADS,cAAc,IAAI,CACV,MAAM,QAAQ;AACrC,MAAI,OAAO,YAAY,WACrB,UAAS,KAAK,QAAQ;AAExB,MAAI,MAAM,aAAa,QAAQ,KAAK,GAAG;;AAGzC,QAAO"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EnvelopePayload, EventType } from "@interfere/types/sdk/envelope";
|
|
2
|
+
|
|
3
|
+
//#region src/plugins/lib/types.d.ts
|
|
4
|
+
type PluginCleanup = () => void;
|
|
5
|
+
interface PluginContext {
|
|
6
|
+
capture<T extends EventType>(type: T, payload: EnvelopePayload<T>): void;
|
|
7
|
+
getSessionId(): string;
|
|
8
|
+
}
|
|
9
|
+
interface Plugin {
|
|
10
|
+
readonly name: string;
|
|
11
|
+
setup(ctx: PluginContext): PluginCleanup | undefined;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { Plugin, PluginCleanup, PluginContext };
|