@scalebun/web 1.0.0 → 1.2.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/dist/bootstrap/SDKBootstrapper.d.ts +6 -6
- package/dist/bootstrap/SDKBootstrapper.js +8 -8
- package/dist/browser.d.ts +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +8 -6
- package/dist/browser.js.map +1 -1
- package/dist/config/endpoints.d.ts +12 -0
- package/dist/config/endpoints.d.ts.map +1 -0
- package/dist/config/endpoints.js +12 -0
- package/dist/config/endpoints.js.map +1 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +5 -3
- package/dist/config/schema.js.map +1 -1
- package/dist/core/breadcrumbs.js +1 -1
- package/dist/core/index.d.ts +13 -13
- package/dist/core/index.js +13 -13
- package/dist/core/observe.js +1 -1
- package/dist/core/pageContext.d.ts +1 -1
- package/dist/features/analytics/AnalyticsFeature.d.ts +2 -2
- package/dist/features/analytics/AnalyticsFeature.js +10 -10
- package/dist/features/analytics/autocapture.js +4 -4
- package/dist/features/analytics/sampler.js +1 -1
- package/dist/features/bugreport/BugReportFeature.d.ts +1 -1
- package/dist/features/bugreport/BugReportFeature.js +1 -1
- package/dist/features/bugreport/collect.js +1 -1
- package/dist/features/bugreport/widget.js +9 -9
- package/dist/features/coach/CoachmarkFeature.d.ts +1 -1
- package/dist/features/coach/CoachmarkFeature.js +5 -5
- package/dist/features/coach/anchor.d.ts +1 -1
- package/dist/features/coach/overlay.d.ts +1 -1
- package/dist/features/coach/overlay.js +21 -21
- package/dist/features/coach/position.d.ts +1 -1
- package/dist/features/coach/predicate.d.ts +1 -1
- package/dist/features/coach/tour.d.ts +4 -4
- package/dist/features/coach/tour.js +1 -1
- package/dist/features/coach/types.d.ts +1 -1
- package/dist/features/coach/wait.d.ts +2 -2
- package/dist/features/config/ConfigFeature.d.ts +1 -1
- package/dist/features/config/ConfigFeature.js +5 -5
- package/dist/features/config/configStore.d.ts +1 -1
- package/dist/features/config/targeting.d.ts +1 -1
- package/dist/features/console/ConsoleFeature.js +3 -3
- package/dist/features/console/normalize.js +2 -2
- package/dist/features/console/throttle.d.ts +1 -1
- package/dist/features/crash/CrashFeature.js +2 -2
- package/dist/features/engage/EngageFeature.d.ts +3 -3
- package/dist/features/engage/EngageFeature.js +5 -5
- package/dist/features/engage/attachments.d.ts +1 -1
- package/dist/features/engage/attachments.js +3 -3
- package/dist/features/engage/gameLogic.d.ts +1 -1
- package/dist/features/engage/gameResolver.d.ts +2 -2
- package/dist/features/engage/gameResolver.js +1 -1
- package/dist/features/engage/inappSlots.d.ts +1 -1
- package/dist/features/engage/inappSlots.js +1 -1
- package/dist/features/engage/normalize.d.ts +1 -1
- package/dist/features/engage/richInApp.d.ts +3 -3
- package/dist/features/engage/richInApp.js +6 -6
- package/dist/features/engage/runtime.d.ts +3 -3
- package/dist/features/engage/runtime.js +7 -7
- package/dist/features/engage/shakeDetector.js +1 -1
- package/dist/features/engage/throttle.d.ts +1 -1
- package/dist/features/engage/transport.d.ts +1 -1
- package/dist/features/engage/transport.js +1 -1
- package/dist/features/engage/triggerEngine.d.ts +1 -1
- package/dist/features/engage/widget/InAppWidget.d.ts +1 -1
- package/dist/features/engage/widget/InAppWidget.js +18 -18
- package/dist/features/engage/widget/SurveyWidget.d.ts +1 -1
- package/dist/features/engage/widget/SurveyWidget.js +66 -66
- package/dist/features/errors/ErrorsFeature.d.ts +1 -1
- package/dist/features/errors/ErrorsFeature.js +6 -6
- package/dist/features/errors/group/fingerprint.js +1 -1
- package/dist/features/errors/lazy.d.ts +3 -3
- package/dist/features/errors/lazy.js +3 -3
- package/dist/features/errors/normalize.d.ts +2 -2
- package/dist/features/errors/normalize.js +2 -2
- package/dist/features/errors/redact.js +1 -1
- package/dist/features/errors/sampling.js +1 -1
- package/dist/features/exit-intent/ExitIntentFeature.js +1 -1
- package/dist/features/exit-intent/engine.js +1 -1
- package/dist/features/forms/index.js +1 -1
- package/dist/features/inapp/InApp2Feature.js +1 -1
- package/dist/features/inapp/anchor/controller.d.ts +2 -2
- package/dist/features/inapp/anchor/controller.js +3 -3
- package/dist/features/inapp/api.d.ts +5 -5
- package/dist/features/inapp/api.js +3 -3
- package/dist/features/inapp/blocks/blocks.d.ts +1 -1
- package/dist/features/inapp/blocks/blocks.js +1 -1
- package/dist/features/inapp/blocks/feedback.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/carousel.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/chart.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/code.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/confetti.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/countdown.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/index.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/index.js +18 -18
- package/dist/features/inapp/blocks/heavy/markdown.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/productgrid.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/qr.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/scratch.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/scratch.js +1 -1
- package/dist/features/inapp/blocks/heavy/slot.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/slot.js +1 -1
- package/dist/features/inapp/blocks/heavy/spinwheel.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/spinwheel.js +1 -1
- package/dist/features/inapp/blocks/heavy/steps.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/streak.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/table.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/unavailable.d.ts +1 -1
- package/dist/features/inapp/blocks/heavy/video.d.ts +1 -1
- package/dist/features/inapp/blocks/styles.js +191 -191
- package/dist/features/inapp/center/bridge.d.ts +3 -3
- package/dist/features/inapp/center/bridge.js +1 -1
- package/dist/features/inapp/center/panel.d.ts +2 -2
- package/dist/features/inapp/center/panel.js +33 -33
- package/dist/features/inapp/center/store.d.ts +1 -1
- package/dist/features/inapp/center/sync.d.ts +1 -1
- package/dist/features/inapp/center/types.d.ts +1 -1
- package/dist/features/inapp/core/analytics.d.ts +3 -3
- package/dist/features/inapp/core/analytics.js +1 -1
- package/dist/features/inapp/core/compat.d.ts +2 -2
- package/dist/features/inapp/core/debugOverlay.d.ts +2 -2
- package/dist/features/inapp/core/debugOverlay.js +12 -12
- package/dist/features/inapp/core/engine.d.ts +3 -3
- package/dist/features/inapp/core/engine.js +10 -10
- package/dist/features/inapp/core/host.js +22 -22
- package/dist/features/inapp/core/metrics.d.ts +1 -1
- package/dist/features/inapp/core/migration.d.ts +2 -2
- package/dist/features/inapp/core/migration.js +2 -2
- package/dist/features/inapp/core/orchestrator.d.ts +1 -1
- package/dist/features/inapp/core/respect.d.ts +1 -1
- package/dist/features/inapp/core/targeting.d.ts +1 -1
- package/dist/features/inapp/core/targeting.js +1 -1
- package/dist/features/inapp/core/triggers.d.ts +1 -1
- package/dist/features/inapp/core/triggers.js +2 -2
- package/dist/features/inapp/inappContract.web.d.ts +1 -1
- package/dist/features/inapp/index.d.ts +15 -15
- package/dist/features/inapp/index.js +10 -10
- package/dist/features/inapp/registry.web.canonical.d.ts +1 -1
- package/dist/features/inapp/registry.web.catalog.d.ts +1 -1
- package/dist/features/inapp/surfaces/banner.d.ts +1 -1
- package/dist/features/inapp/surfaces/banner.js +1 -1
- package/dist/features/inapp/surfaces/checklist.d.ts +1 -1
- package/dist/features/inapp/surfaces/coachmark.d.ts +1 -1
- package/dist/features/inapp/surfaces/coachmark.js +2 -2
- package/dist/features/inapp/surfaces/hotspot.d.ts +1 -1
- package/dist/features/inapp/surfaces/hotspot.js +2 -2
- package/dist/features/inapp/surfaces/inline.d.ts +4 -4
- package/dist/features/inapp/surfaces/inline.js +11 -11
- package/dist/features/inapp/surfaces/launcher.d.ts +1 -1
- package/dist/features/inapp/surfaces/modal.d.ts +1 -1
- package/dist/features/inapp/surfaces/modal.js +2 -2
- package/dist/features/inapp/surfaces/mount.d.ts +4 -4
- package/dist/features/inapp/surfaces/mount.js +4 -4
- package/dist/features/inapp/surfaces/palette.d.ts +1 -1
- package/dist/features/inapp/surfaces/palette.js +1 -1
- package/dist/features/inapp/surfaces/panel.d.ts +1 -1
- package/dist/features/inapp/surfaces/popover.d.ts +1 -1
- package/dist/features/inapp/surfaces/popover.js +2 -2
- package/dist/features/inapp/surfaces/render.d.ts +4 -4
- package/dist/features/inapp/surfaces/render.d.ts.map +1 -1
- package/dist/features/inapp/surfaces/render.js +23 -19
- package/dist/features/inapp/surfaces/render.js.map +1 -1
- package/dist/features/inapp/surfaces/slideover.d.ts +1 -1
- package/dist/features/inapp/surfaces/slideover.js +1 -1
- package/dist/features/inapp/surfaces/styles.js +179 -179
- package/dist/features/inapp/surfaces/surface.d.ts +4 -4
- package/dist/features/inapp/surfaces/surface.js +2 -2
- package/dist/features/inapp/surfaces/takeover.d.ts +1 -1
- package/dist/features/inapp/surfaces/takeover.js +2 -2
- package/dist/features/inapp/surfaces/toast.d.ts +1 -1
- package/dist/features/inapp/surfaces/toast.js +1 -1
- package/dist/features/inapp/surfaces/toolbar.d.ts +1 -1
- package/dist/features/inapp/surfaces/toolbar.js +2 -2
- package/dist/features/inapp/surfaces/tour.d.ts +1 -1
- package/dist/features/inapp/surfaces/tour.js +5 -5
- package/dist/features/inbox/InboxFeature.d.ts +1 -1
- package/dist/features/inbox/InboxFeature.js +5 -5
- package/dist/features/inbox/runtime.d.ts +2 -2
- package/dist/features/inbox/runtime.js +3 -3
- package/dist/features/inbox/store.d.ts +1 -1
- package/dist/features/inbox/sync.d.ts +2 -2
- package/dist/features/inbox/sync.js +1 -1
- package/dist/features/inbox/widget/InboxWidget.d.ts +1 -1
- package/dist/features/inbox/widget/InboxWidget.js +85 -85
- package/dist/features/journey/InteractionTracker.js +1 -1
- package/dist/features/journey/JourneyFeature.js +3 -3
- package/dist/features/manifest.d.ts +1 -1
- package/dist/features/manifest.js +18 -18
- package/dist/features/network/NetworkFeature.d.ts +1 -1
- package/dist/features/network/NetworkFeature.js +10 -10
- package/dist/features/network/capture/body.d.ts +1 -1
- package/dist/features/network/capture/body.js +1 -1
- package/dist/features/network/classify.d.ts +1 -1
- package/dist/features/network/fetchInterceptor.d.ts +1 -1
- package/dist/features/network/fetchInterceptor.js +1 -1
- package/dist/features/network/intercept/beacon.d.ts +1 -1
- package/dist/features/network/intercept/sse.d.ts +1 -1
- package/dist/features/network/intercept/streams.d.ts +4 -4
- package/dist/features/network/intercept/streams.js +3 -3
- package/dist/features/network/intercept/websocket.d.ts +1 -1
- package/dist/features/network/lazy.d.ts +3 -3
- package/dist/features/network/lazy.js +2 -2
- package/dist/features/network/normalize.d.ts +1 -1
- package/dist/features/network/normalize.js +3 -3
- package/dist/features/network/parse/graphql.d.ts +1 -1
- package/dist/features/network/sampler.js +1 -1
- package/dist/features/network/timing.d.ts +1 -1
- package/dist/features/network/xhrInterceptor.d.ts +1 -1
- package/dist/features/network/xhrInterceptor.js +1 -1
- package/dist/features/performance/PerformanceFeature.d.ts +2 -2
- package/dist/features/performance/PerformanceFeature.js +11 -11
- package/dist/features/performance/longTasks.js +1 -1
- package/dist/features/performance/normalize.js +1 -1
- package/dist/features/performance/sampler.js +1 -1
- package/dist/features/performance/trace/index.d.ts +4 -4
- package/dist/features/performance/trace/index.js +3 -3
- package/dist/features/performance/trace/pageload.d.ts +1 -1
- package/dist/features/performance/trace/pageload.js +1 -1
- package/dist/features/performance/trace/transaction.d.ts +2 -2
- package/dist/features/performance/trace/transaction.js +2 -2
- package/dist/features/profiler/ProfilerFeature.js +1 -1
- package/dist/features/push/PushFeature.d.ts +4 -4
- package/dist/features/push/PushFeature.js +3 -3
- package/dist/features/push/softAsk.d.ts +1 -1
- package/dist/features/push/softAsk.js +26 -26
- package/dist/features/replay/ReplayFeature.d.ts +1 -1
- package/dist/features/replay/ReplayFeature.js +12 -12
- package/dist/features/replay/engine/canvas.d.ts +2 -2
- package/dist/features/replay/engine/crossOrigin.d.ts +1 -1
- package/dist/features/replay/engine/crossOrigin.js +3 -3
- package/dist/features/replay/engine/cssom.d.ts +2 -2
- package/dist/features/replay/engine/iframe.d.ts +2 -2
- package/dist/features/replay/engine/iframe.js +3 -3
- package/dist/features/replay/engine/interactions.d.ts +1 -1
- package/dist/features/replay/engine/interactions.js +1 -1
- package/dist/features/replay/engine/mutations.d.ts +3 -3
- package/dist/features/replay/engine/mutations.js +2 -2
- package/dist/features/replay/engine/player.d.ts +2 -2
- package/dist/features/replay/engine/player.js +1 -1
- package/dist/features/replay/engine/rebuild.d.ts +1 -1
- package/dist/features/replay/engine/replayWorker.js +16 -16
- package/dist/features/replay/engine/resources.d.ts +1 -1
- package/dist/features/replay/engine/resources.js +1 -1
- package/dist/features/replay/engine/snapshot.d.ts +2 -2
- package/dist/features/replay/engine/snapshot.js +1 -1
- package/dist/features/replay/engine/traverse.d.ts +1 -1
- package/dist/features/replay/lifecycle/recorder.d.ts +1 -1
- package/dist/features/replay/lifecycle/recorder.js +20 -20
- package/dist/features/replay/lifecycle/sampling.js +1 -1
- package/dist/features/replay/lifecycle/viewContext.js +1 -1
- package/dist/features/scroll/index.js +1 -1
- package/dist/features/session/sessionManager.d.ts +1 -1
- package/dist/features/session/sessionManager.js +2 -2
- package/dist/features/session/sessionStore.js +1 -1
- package/dist/features/watchdog/WatchdogFeature.d.ts +1 -1
- package/dist/features/watchdog/WatchdogFeature.js +1 -1
- package/dist/features/watchdog/collectors.d.ts +1 -1
- package/dist/features/watchdog/collectors.js +1 -1
- package/dist/features/watchdog/engine.js +8 -8
- package/dist/features/watchdog/incidents.d.ts +1 -1
- package/dist/features/watchdog/incidents.js +1 -1
- package/dist/features/watchdog/rollup.d.ts +1 -1
- package/dist/features/watchdog/rollup.js +1 -1
- package/dist/features/webVitals/WebVitalsFeature.js +4 -4
- package/dist/features/webVitals/observe.d.ts +1 -1
- package/dist/features/webVitals/observe.js +1 -1
- package/dist/features/webperf/WebPerfFeature.d.ts +1 -1
- package/dist/features/webperf/WebPerfFeature.js +3 -3
- package/dist/features/webperf/collectors.js +1 -1
- package/dist/inapp.d.ts +1 -1
- package/dist/inapp.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/pipeline/index.d.ts +1 -1
- package/dist/pipeline/index.js +1 -1
- package/dist/pipeline/pipeline.d.ts +3 -3
- package/dist/pipeline/pipeline.js +4 -4
- package/dist/public/ScaleBunFacade.d.ts +18 -18
- package/dist/public/ScaleBunFacade.js +11 -11
- package/dist/public/index.d.ts +4 -4
- package/dist/public/index.js +2 -2
- package/dist/scalebun-push-sw.js +236 -236
- package/dist/scalebun.min.js +17 -17
- package/dist/scalebun.min.js.map +4 -4
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.js +1 -1
- package/dist/transport/httpClient.d.ts +1 -1
- package/dist/transport/httpClient.js +3 -3
- package/dist/transport/index.d.ts +1 -1
- package/dist/transport/index.js +1 -1
- package/package.json +7 -7
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { now, getReplayCoord } from '../../core';
|
|
1
|
+
import { now, getReplayCoord } from '../../core/index.js';
|
|
2
2
|
const INITIAL_STATE = { unreadCount: 0, total: 0, syncStatus: 'idle' };
|
|
3
3
|
export class InboxFeature {
|
|
4
4
|
constructor() {
|
|
@@ -90,7 +90,7 @@ export class InboxFeature {
|
|
|
90
90
|
this.remoteTheme = theme;
|
|
91
91
|
if (!this.widget)
|
|
92
92
|
return; // headless host, or not mounted yet — mount() will pick it up
|
|
93
|
-
void import('./widget/InboxWidget').then(({ mountInbox }) => {
|
|
93
|
+
void import('./widget/InboxWidget.js').then(({ mountInbox }) => {
|
|
94
94
|
this.widget?.destroy();
|
|
95
95
|
this.widget = mountInbox(this.controller(), this.mountOpts ?? {}, this.remoteTheme);
|
|
96
96
|
});
|
|
@@ -109,7 +109,7 @@ export class InboxFeature {
|
|
|
109
109
|
if (this.loading)
|
|
110
110
|
return this.loading;
|
|
111
111
|
this.loading = (async () => {
|
|
112
|
-
const [{ InboxRuntime }, { InboxStore }] = await Promise.all([import('./runtime'), import('./store')]);
|
|
112
|
+
const [{ InboxRuntime }, { InboxStore }] = await Promise.all([import('./runtime.js'), import('./store.js')]);
|
|
113
113
|
const store = new InboxStore(this.ctx?.deviceId || 'anon'); // per-identity (A1.4 re-scopes on identify)
|
|
114
114
|
const rt = new InboxRuntime({
|
|
115
115
|
trackEvent: (n, p) => this.ctx?.trackEvent(n, p),
|
|
@@ -124,7 +124,7 @@ export class InboxFeature {
|
|
|
124
124
|
this.pendingCta.clear();
|
|
125
125
|
await rt.hydrate(); // A1.2 — restore the persisted snapshot, then emit the real initial state
|
|
126
126
|
// A1.3 — build the delta-sync engine (shares the one store) + kick an initial pull (best-effort).
|
|
127
|
-
const { InboxSync, InboxTransport } = await import('./sync');
|
|
127
|
+
const { InboxSync, InboxTransport } = await import('./sync.js');
|
|
128
128
|
const transport = new InboxTransport(this.ctx?.apiBaseUrl ?? '', this.ctx?.clientKey ?? '', this.ctx?.deviceId ?? 'anon');
|
|
129
129
|
this.syncEngine = new InboxSync({
|
|
130
130
|
transport, store, runtime: rt,
|
|
@@ -174,7 +174,7 @@ export class InboxFeature {
|
|
|
174
174
|
if (typeof document === 'undefined')
|
|
175
175
|
return;
|
|
176
176
|
void this.ensureRuntime().then(async () => {
|
|
177
|
-
const { mountInbox } = await import('./widget/InboxWidget');
|
|
177
|
+
const { mountInbox } = await import('./widget/InboxWidget.js');
|
|
178
178
|
this.widget?.destroy();
|
|
179
179
|
this.mountOpts = opts ?? {};
|
|
180
180
|
this.widget = mountInbox(this.controller(), this.mountOpts, this.remoteTheme);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type InboxStorePort } from './store';
|
|
2
|
-
import type { InboxMessage, InboxQueryOptions, InboxPage, InboxState, InboxCta, InboxSyncStatus, InboxDirtyOp } from './types';
|
|
1
|
+
import { type InboxStorePort } from './store.js';
|
|
2
|
+
import type { InboxMessage, InboxQueryOptions, InboxPage, InboxState, InboxCta, InboxSyncStatus, InboxDirtyOp } from './types.js';
|
|
3
3
|
export interface InboxRuntimeDeps {
|
|
4
4
|
trackEvent: (name: string, props?: Record<string, unknown>) => void;
|
|
5
5
|
replayCoord: () => {
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
* cross-tab. The in-memory map stays the hot read path (query/sort/paginate never touch IDB).
|
|
9
9
|
* A1.3 adds the delta sync + conflict resolution on top of this same surface.
|
|
10
10
|
*/
|
|
11
|
-
import { INBOX_EVENTS } from './types';
|
|
12
|
-
import { InboxStore, NOOP_STORE } from './store';
|
|
13
|
-
import { mergeMessage } from './sync';
|
|
11
|
+
import { INBOX_EVENTS } from './types.js';
|
|
12
|
+
import { InboxStore, NOOP_STORE } from './store.js';
|
|
13
|
+
import { mergeMessage } from './sync.js';
|
|
14
14
|
const RANK = { unread: 0, read: 1, archived: 2, deleted: 3 };
|
|
15
15
|
const DEFAULT_LIMIT = 20;
|
|
16
16
|
function encodeCursor(m) {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Graceful no-op when IndexedDB is unavailable (SSR / private mode / blocked): every method degrades to
|
|
9
9
|
* a no-op and the runtime's in-memory map becomes the (session-only) memory tier — never throws.
|
|
10
10
|
*/
|
|
11
|
-
import type { InboxMessage } from './types';
|
|
11
|
+
import type { InboxMessage } from './types.js';
|
|
12
12
|
/** The durable-tier port the runtime depends on (so tests inject a fake, no real IDB needed). */
|
|
13
13
|
export interface InboxStorePort {
|
|
14
14
|
hydrate(): Promise<InboxMessage[]>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { InboxMessage, InboxMessageState, InboxDirtyOp, InboxRemoteTheme, InboxSyncRequest, InboxSyncResponse, InboxSyncTransport, InboxSyncStatus } from './types';
|
|
2
|
-
import type { InboxStorePort } from './store';
|
|
1
|
+
import type { InboxMessage, InboxMessageState, InboxDirtyOp, InboxRemoteTheme, InboxSyncRequest, InboxSyncResponse, InboxSyncTransport, InboxSyncStatus } from './types.js';
|
|
2
|
+
import type { InboxStorePort } from './store.js';
|
|
3
3
|
/** Pure two-way merge for one message. `local` undefined = brand-new from the server. */
|
|
4
4
|
export declare function mergeMessage(local: InboxMessage | undefined, server: InboxMessage): InboxMessage;
|
|
5
5
|
/** Highest lifecycle rank reached — exported for the runtime's DAG guard + tests. */
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* The message store doubles as the outbox: a local mutation flags `_dirty`; sync pushes those as ops and
|
|
11
11
|
* clears the flag on ack. Offline/failure keeps the flag (already persisted) → retried next sync.
|
|
12
12
|
*/
|
|
13
|
-
import { isOnline } from '../../core/retry';
|
|
13
|
+
import { isOnline } from '../../core/retry.js';
|
|
14
14
|
const RANK = { unread: 0, read: 1, archived: 2, deleted: 3 };
|
|
15
15
|
const CONTENT_KEYS = [
|
|
16
16
|
'revision', 'campaignId', 'category', 'priority', 'title', 'body', 'html',
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* boundary, and this file reads them with fallbacks rather than declaring them, so an outer value
|
|
14
14
|
* wins. `mount({accent})` overrides even that. See `styles()` for why the distinction matters.
|
|
15
15
|
*/
|
|
16
|
-
import { injectStyle } from '../../../core';
|
|
17
|
-
import { DEFAULT_INBOX_LABELS } from '../types';
|
|
16
|
+
import { injectStyle } from '../../../core/index.js';
|
|
17
|
+
import { DEFAULT_INBOX_LABELS } from '../types.js';
|
|
18
18
|
const PIN_SVG = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M12 17v5M9 3h6l-1 6 3 3v2H7v-2l3-3z"/></svg>';
|
|
19
19
|
const ARCHIVE_SVG = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M3 7h18v3H3zM5 10v10h14V10M9 14h6"/></svg>';
|
|
20
20
|
const TRASH_SVG = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13"/></svg>';
|
|
@@ -101,89 +101,89 @@ function styles(dark, corner, rtl, layout, accent, remote) {
|
|
|
101
101
|
const radSm = (fallback) => v('radius-sm', fallback);
|
|
102
102
|
// Only what the caller explicitly asked for is declared — declaring more is what broke overrides.
|
|
103
103
|
const forced = accent ? `--scalebun-inbox-accent:${accent};` : '';
|
|
104
|
-
return `
|
|
105
|
-
:host{all:initial;direction:${rtl ? 'rtl' : 'ltr'};${forced}}
|
|
106
|
-
*{box-sizing:border-box;font-family:${FONT}}
|
|
107
|
-
button:focus-visible,.row:focus-visible,.tab:focus-visible{outline:2px solid ${PP};outline-offset:2px}
|
|
108
|
-
.live{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
|
|
109
|
-
.bell{position:fixed;${vy}:22px;${side}:22px;width:52px;height:52px;border-radius:50%;border:none;cursor:pointer;
|
|
110
|
-
background:${PP};color:#fff;display:grid;place-items:center;box-shadow:0 6px 24px rgba(108,92,231,.4);z-index:${Z}}
|
|
111
|
-
.bell:hover{filter:brightness(1.06)}
|
|
112
|
-
.bell svg{width:22px;height:22px}
|
|
113
|
-
.badge{position:absolute;top:-4px;${side}:-4px;min-width:20px;height:20px;padding:0 5px;border-radius:10px;
|
|
114
|
-
background:${BADGE};color:#fff;font-size:11px;font-weight:700;display:none;align-items:center;justify-content:center;line-height:1}
|
|
115
|
-
.badge.on{display:flex}
|
|
116
|
-
.scrim{position:fixed;inset:0;background:rgba(10,8,16,.42);z-index:calc(${Z} + 1);opacity:0;pointer-events:none;transition:opacity .2s}
|
|
117
|
-
.scrim.on{opacity:1;pointer-events:auto}
|
|
118
|
-
.panel{position:fixed;${vy === 'bottom' ? 'bottom:0;top:0' : 'top:0;bottom:0'};${side}:0;width:${WIDTH};max-width:94vw;background:${BG};color:${FG};
|
|
119
|
-
z-index:calc(${Z} + 2);display:flex;flex-direction:column;box-shadow:${SHADOW};
|
|
120
|
-
transform:translateX(${side === 'right' ? '100%' : '-100%'});transition:transform .26s cubic-bezier(.4,0,.2,1)}
|
|
121
|
-
.panel.open{transform:translateX(0)}
|
|
122
|
-
.hd{display:flex;align-items:center;justify-content:space-between;padding:15px 16px;border-bottom:1px solid ${LINE}}
|
|
123
|
-
.hd .ti{font-size:15px;font-weight:700}
|
|
124
|
-
.hd .mt{font-size:12px;color:${SUB};margin-top:2px}
|
|
125
|
-
.x{width:30px;height:30px;border-radius:${radSm("8px")};border:1px solid ${LINE};background:${SURF};color:${SUB};cursor:pointer;font-size:17px;line-height:1;display:grid;place-items:center}
|
|
126
|
-
.x:hover{color:${FG}}
|
|
127
|
-
.tabs{display:flex;gap:6px;padding:8px 12px;border-bottom:1px solid ${LINE};overflow-x:auto}
|
|
128
|
-
.tab{flex-shrink:0;border:none;background:${SURF};color:${SUB};border-radius:999px;padding:5px 12px;font-size:12px;font-weight:600;cursor:pointer}
|
|
129
|
-
.tab.on{background:${PP};color:#fff}
|
|
130
|
-
.body{flex:1;overflow-y:auto;padding:6px}
|
|
131
|
-
.empty{padding:48px 20px;text-align:center;color:${SUB};font-size:13px}
|
|
132
|
-
.empty b{display:block;color:${FG};font-size:14px;margin-bottom:5px}
|
|
133
|
-
.list{display:flex;flex-direction:column}
|
|
134
|
-
.row{position:relative;display:flex;gap:${GAP};padding:12px 12px 12px 15px;border-radius:${rad("10px")};cursor:pointer}
|
|
135
|
-
.row:hover{background:${SURF}}
|
|
136
|
-
.row.unread{background:${UNREAD}}
|
|
137
|
-
.dot{position:absolute;left:5px;top:18px;width:7px;height:7px;border-radius:50%;background:${PP};opacity:0}
|
|
138
|
-
.row.unread .dot{opacity:1}
|
|
139
|
-
.ic{flex-shrink:0;width:34px;height:34px;border-radius:${rad("9px")};background:${SURF};display:grid;place-items:center;overflow:hidden;font-weight:700;color:${PP};font-size:14px}
|
|
140
|
-
.ic img{width:100%;height:100%;object-fit:cover}
|
|
141
|
-
.rc{flex:1;min-width:0}
|
|
142
|
-
.rtop{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
|
|
143
|
-
.rt{font-size:13.5px;font-weight:600;color:${FG};overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
144
|
-
.row.unread .rt{font-weight:700}
|
|
145
|
-
.rtime{flex-shrink:0;font-size:11px;color:${SUB}}
|
|
146
|
-
.rb{font-size:12.5px;color:${SUB};line-height:1.4;margin-top:2px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
|
|
147
|
-
.rcta{display:flex;gap:7px;margin-top:8px}
|
|
148
|
-
.rcta button{background:${PP};color:#fff;border:none;border-radius:${radSm("7px")};padding:5px 11px;font-size:12px;font-weight:600;cursor:pointer}
|
|
149
|
-
.rcta button.sec{background:${SURF};color:${FG}}
|
|
150
|
-
/* ⚠️ Was \`position:absolute\` floating over the row, which meant NO space was reserved for it and the
|
|
151
|
-
title ran underneath — the buttons masked their own row's text (and in RTL they landed on top of
|
|
152
|
-
the title rather than the timestamp). A hover-only overlay only looks fine while the text is short.
|
|
153
|
-
Now a real flex child: it always occupies its column, so nothing can ever slide under it, and
|
|
154
|
-
\`visibility\` (not \`display\`) means revealing it on hover causes no reflow. */
|
|
155
|
-
.ract{flex-shrink:0;align-self:flex-start;display:flex;gap:2px;border-radius:${radSm("8px")};padding:2px;visibility:hidden}
|
|
156
|
-
.row:hover .ract,.row:focus-within .ract{visibility:visible}
|
|
157
|
-
.ract button{width:26px;height:26px;border:none;background:none;color:${SUB};cursor:pointer;border-radius:${radSm("6px")};display:grid;place-items:center}
|
|
158
|
-
.ract button:hover{background:${SURF};color:${FG}}
|
|
159
|
-
.ract button.on{color:${PP}}
|
|
160
|
-
.ract svg{width:15px;height:15px}
|
|
161
|
-
${layout !== 'dropdown' ? '' : `
|
|
162
|
-
/* ── dropdown ────────────────────────────────────────────────────────────────
|
|
163
|
-
A compact popover anchored under the host's own trigger, for a bell that already lives in a navbar.
|
|
164
|
-
Everything below OVERRIDES the drawer rules above rather than forking the stylesheet — the rows,
|
|
165
|
-
tabs, a11y wiring and theming are identical, so only geometry changes.
|
|
166
|
-
|
|
167
|
-
⚠️ \`inset:auto\` first: the drawer pins all four edges, and leaving even one of them set makes the
|
|
168
|
-
panel stretch instead of sizing to its content. The anchor coordinates are written inline by
|
|
169
|
-
\`positionDropdown()\` at open time, because they depend on where the trigger is on screen. */
|
|
170
|
-
.panel{inset:auto;top:auto;bottom:auto;left:auto;right:auto;
|
|
171
|
-
height:auto;max-height:min(70vh,520px);width:min(${WIDTH},calc(100vw - 24px));
|
|
172
|
-
border:1px solid ${LINE};border-radius:${rad('14px')};overflow:hidden;
|
|
173
|
-
transform:translateY(-6px) scale(.98);opacity:0;transform-origin:top ${side};
|
|
174
|
-
transition:opacity .14s ease-out,transform .14s ease-out}
|
|
175
|
-
.panel.open{transform:none;opacity:1}
|
|
176
|
-
/* No dimming: a dropdown is a light-touch surface, and a full-screen scrim over a navbar menu reads
|
|
177
|
-
as a modal. It still catches outside clicks — hence transparent rather than removed. */
|
|
178
|
-
.scrim{background:transparent}
|
|
179
|
-
.bell{display:none} /* the host's trigger IS the bell here */
|
|
180
|
-
.hd{padding:12px 14px}
|
|
181
|
-
.body{max-height:none}
|
|
182
|
-
.foot{display:flex;border-top:1px solid ${LINE};padding:8px}
|
|
183
|
-
.foot button{flex:1;border:none;background:none;color:${PP};font-size:13px;font-weight:600;
|
|
184
|
-
cursor:pointer;padding:8px;border-radius:${radSm('8px')}}
|
|
185
|
-
.foot button:hover{background:${SURF}}
|
|
186
|
-
`}
|
|
104
|
+
return `
|
|
105
|
+
:host{all:initial;direction:${rtl ? 'rtl' : 'ltr'};${forced}}
|
|
106
|
+
*{box-sizing:border-box;font-family:${FONT}}
|
|
107
|
+
button:focus-visible,.row:focus-visible,.tab:focus-visible{outline:2px solid ${PP};outline-offset:2px}
|
|
108
|
+
.live{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
|
|
109
|
+
.bell{position:fixed;${vy}:22px;${side}:22px;width:52px;height:52px;border-radius:50%;border:none;cursor:pointer;
|
|
110
|
+
background:${PP};color:#fff;display:grid;place-items:center;box-shadow:0 6px 24px rgba(108,92,231,.4);z-index:${Z}}
|
|
111
|
+
.bell:hover{filter:brightness(1.06)}
|
|
112
|
+
.bell svg{width:22px;height:22px}
|
|
113
|
+
.badge{position:absolute;top:-4px;${side}:-4px;min-width:20px;height:20px;padding:0 5px;border-radius:10px;
|
|
114
|
+
background:${BADGE};color:#fff;font-size:11px;font-weight:700;display:none;align-items:center;justify-content:center;line-height:1}
|
|
115
|
+
.badge.on{display:flex}
|
|
116
|
+
.scrim{position:fixed;inset:0;background:rgba(10,8,16,.42);z-index:calc(${Z} + 1);opacity:0;pointer-events:none;transition:opacity .2s}
|
|
117
|
+
.scrim.on{opacity:1;pointer-events:auto}
|
|
118
|
+
.panel{position:fixed;${vy === 'bottom' ? 'bottom:0;top:0' : 'top:0;bottom:0'};${side}:0;width:${WIDTH};max-width:94vw;background:${BG};color:${FG};
|
|
119
|
+
z-index:calc(${Z} + 2);display:flex;flex-direction:column;box-shadow:${SHADOW};
|
|
120
|
+
transform:translateX(${side === 'right' ? '100%' : '-100%'});transition:transform .26s cubic-bezier(.4,0,.2,1)}
|
|
121
|
+
.panel.open{transform:translateX(0)}
|
|
122
|
+
.hd{display:flex;align-items:center;justify-content:space-between;padding:15px 16px;border-bottom:1px solid ${LINE}}
|
|
123
|
+
.hd .ti{font-size:15px;font-weight:700}
|
|
124
|
+
.hd .mt{font-size:12px;color:${SUB};margin-top:2px}
|
|
125
|
+
.x{width:30px;height:30px;border-radius:${radSm("8px")};border:1px solid ${LINE};background:${SURF};color:${SUB};cursor:pointer;font-size:17px;line-height:1;display:grid;place-items:center}
|
|
126
|
+
.x:hover{color:${FG}}
|
|
127
|
+
.tabs{display:flex;gap:6px;padding:8px 12px;border-bottom:1px solid ${LINE};overflow-x:auto}
|
|
128
|
+
.tab{flex-shrink:0;border:none;background:${SURF};color:${SUB};border-radius:999px;padding:5px 12px;font-size:12px;font-weight:600;cursor:pointer}
|
|
129
|
+
.tab.on{background:${PP};color:#fff}
|
|
130
|
+
.body{flex:1;overflow-y:auto;padding:6px}
|
|
131
|
+
.empty{padding:48px 20px;text-align:center;color:${SUB};font-size:13px}
|
|
132
|
+
.empty b{display:block;color:${FG};font-size:14px;margin-bottom:5px}
|
|
133
|
+
.list{display:flex;flex-direction:column}
|
|
134
|
+
.row{position:relative;display:flex;gap:${GAP};padding:12px 12px 12px 15px;border-radius:${rad("10px")};cursor:pointer}
|
|
135
|
+
.row:hover{background:${SURF}}
|
|
136
|
+
.row.unread{background:${UNREAD}}
|
|
137
|
+
.dot{position:absolute;left:5px;top:18px;width:7px;height:7px;border-radius:50%;background:${PP};opacity:0}
|
|
138
|
+
.row.unread .dot{opacity:1}
|
|
139
|
+
.ic{flex-shrink:0;width:34px;height:34px;border-radius:${rad("9px")};background:${SURF};display:grid;place-items:center;overflow:hidden;font-weight:700;color:${PP};font-size:14px}
|
|
140
|
+
.ic img{width:100%;height:100%;object-fit:cover}
|
|
141
|
+
.rc{flex:1;min-width:0}
|
|
142
|
+
.rtop{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
|
|
143
|
+
.rt{font-size:13.5px;font-weight:600;color:${FG};overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
144
|
+
.row.unread .rt{font-weight:700}
|
|
145
|
+
.rtime{flex-shrink:0;font-size:11px;color:${SUB}}
|
|
146
|
+
.rb{font-size:12.5px;color:${SUB};line-height:1.4;margin-top:2px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
|
|
147
|
+
.rcta{display:flex;gap:7px;margin-top:8px}
|
|
148
|
+
.rcta button{background:${PP};color:#fff;border:none;border-radius:${radSm("7px")};padding:5px 11px;font-size:12px;font-weight:600;cursor:pointer}
|
|
149
|
+
.rcta button.sec{background:${SURF};color:${FG}}
|
|
150
|
+
/* ⚠️ Was \`position:absolute\` floating over the row, which meant NO space was reserved for it and the
|
|
151
|
+
title ran underneath — the buttons masked their own row's text (and in RTL they landed on top of
|
|
152
|
+
the title rather than the timestamp). A hover-only overlay only looks fine while the text is short.
|
|
153
|
+
Now a real flex child: it always occupies its column, so nothing can ever slide under it, and
|
|
154
|
+
\`visibility\` (not \`display\`) means revealing it on hover causes no reflow. */
|
|
155
|
+
.ract{flex-shrink:0;align-self:flex-start;display:flex;gap:2px;border-radius:${radSm("8px")};padding:2px;visibility:hidden}
|
|
156
|
+
.row:hover .ract,.row:focus-within .ract{visibility:visible}
|
|
157
|
+
.ract button{width:26px;height:26px;border:none;background:none;color:${SUB};cursor:pointer;border-radius:${radSm("6px")};display:grid;place-items:center}
|
|
158
|
+
.ract button:hover{background:${SURF};color:${FG}}
|
|
159
|
+
.ract button.on{color:${PP}}
|
|
160
|
+
.ract svg{width:15px;height:15px}
|
|
161
|
+
${layout !== 'dropdown' ? '' : `
|
|
162
|
+
/* ── dropdown ────────────────────────────────────────────────────────────────
|
|
163
|
+
A compact popover anchored under the host's own trigger, for a bell that already lives in a navbar.
|
|
164
|
+
Everything below OVERRIDES the drawer rules above rather than forking the stylesheet — the rows,
|
|
165
|
+
tabs, a11y wiring and theming are identical, so only geometry changes.
|
|
166
|
+
|
|
167
|
+
⚠️ \`inset:auto\` first: the drawer pins all four edges, and leaving even one of them set makes the
|
|
168
|
+
panel stretch instead of sizing to its content. The anchor coordinates are written inline by
|
|
169
|
+
\`positionDropdown()\` at open time, because they depend on where the trigger is on screen. */
|
|
170
|
+
.panel{inset:auto;top:auto;bottom:auto;left:auto;right:auto;
|
|
171
|
+
height:auto;max-height:min(70vh,520px);width:min(${WIDTH},calc(100vw - 24px));
|
|
172
|
+
border:1px solid ${LINE};border-radius:${rad('14px')};overflow:hidden;
|
|
173
|
+
transform:translateY(-6px) scale(.98);opacity:0;transform-origin:top ${side};
|
|
174
|
+
transition:opacity .14s ease-out,transform .14s ease-out}
|
|
175
|
+
.panel.open{transform:none;opacity:1}
|
|
176
|
+
/* No dimming: a dropdown is a light-touch surface, and a full-screen scrim over a navbar menu reads
|
|
177
|
+
as a modal. It still catches outside clicks — hence transparent rather than removed. */
|
|
178
|
+
.scrim{background:transparent}
|
|
179
|
+
.bell{display:none} /* the host's trigger IS the bell here */
|
|
180
|
+
.hd{padding:12px 14px}
|
|
181
|
+
.body{max-height:none}
|
|
182
|
+
.foot{display:flex;border-top:1px solid ${LINE};padding:8px}
|
|
183
|
+
.foot button{flex:1;border:none;background:none;color:${PP};font-size:13px;font-weight:600;
|
|
184
|
+
cursor:pointer;padding:8px;border-radius:${radSm('8px')}}
|
|
185
|
+
.foot button:hover{background:${SURF}}
|
|
186
|
+
`}
|
|
187
187
|
@media(prefers-reduced-motion:reduce){.panel,.scrim{transition:none}}`;
|
|
188
188
|
}
|
|
189
189
|
/**
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* merged into a single row, so per-element click analytics could not exist. The selector was always
|
|
10
10
|
* unmasked, so this never was the SDK's privacy boundary anyway.
|
|
11
11
|
*/
|
|
12
|
-
import { RageDetector, DeadClickWatcher } from './friction';
|
|
12
|
+
import { RageDetector, DeadClickWatcher } from './friction.js';
|
|
13
13
|
export class InteractionTracker {
|
|
14
14
|
constructor(emit, opts = {},
|
|
15
15
|
/** Raise a capture signal ('rage'|'dead') onto the bus — arms friction-triggered features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { uuid, now, getReplayCoord } from '../../core';
|
|
2
|
-
import { NavigationTracker } from './NavigationTracker';
|
|
3
|
-
import { InteractionTracker } from './InteractionTracker';
|
|
1
|
+
import { uuid, now, getReplayCoord } from '../../core/index.js';
|
|
2
|
+
import { NavigationTracker } from './NavigationTracker.js';
|
|
3
|
+
import { InteractionTracker } from './InteractionTracker.js';
|
|
4
4
|
export class JourneyFeature {
|
|
5
5
|
constructor() {
|
|
6
6
|
this.name = 'journey';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IFeature } from '@scalebun/sdk-contracts';
|
|
2
|
-
import type { Capabilities } from '../core/capabilities';
|
|
2
|
+
import type { Capabilities } from '../core/capabilities.js';
|
|
3
3
|
/**
|
|
4
4
|
* The feature registry source. Each capture feature vertical (errors, network, webVitals, replay,
|
|
5
5
|
* …) appends its instance here — this is the append-only seam from WEB-SDK-PLAN.md §1. Bootstrap
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import { AnalyticsFeature } from './analytics/AnalyticsFeature';
|
|
2
|
-
import { ConfigFeature } from './config/ConfigFeature';
|
|
3
|
-
import { ErrorsFeature } from './errors/ErrorsFeature';
|
|
4
|
-
import { NetworkFeature } from './network/NetworkFeature';
|
|
5
|
-
import { WebVitalsFeature } from './webVitals/WebVitalsFeature';
|
|
6
|
-
import { PerformanceFeature } from './performance/PerformanceFeature';
|
|
7
|
-
import { JourneyFeature } from './journey/JourneyFeature';
|
|
8
|
-
import { ConsoleFeature } from './console/ConsoleFeature';
|
|
9
|
-
import { BugReportFeature } from './bugreport/BugReportFeature';
|
|
10
|
-
import { CrashFeature } from './crash/CrashFeature';
|
|
11
|
-
import { EngageFeature } from './engage/EngageFeature';
|
|
12
|
-
import { InboxFeature } from './inbox/InboxFeature';
|
|
13
|
-
import { WebPerfFeature } from './webperf/WebPerfFeature';
|
|
14
|
-
import { ProfilerFeature } from './profiler/ProfilerFeature';
|
|
15
|
-
import { WatchdogFeature } from './watchdog/WatchdogFeature';
|
|
16
|
-
import { ExitIntentFeature } from './exit-intent/ExitIntentFeature';
|
|
17
|
-
import { InApp2Feature } from './inapp/InApp2Feature';
|
|
18
|
-
import { ReplayFeature } from './replay/ReplayFeature';
|
|
1
|
+
import { AnalyticsFeature } from './analytics/AnalyticsFeature.js';
|
|
2
|
+
import { ConfigFeature } from './config/ConfigFeature.js';
|
|
3
|
+
import { ErrorsFeature } from './errors/ErrorsFeature.js';
|
|
4
|
+
import { NetworkFeature } from './network/NetworkFeature.js';
|
|
5
|
+
import { WebVitalsFeature } from './webVitals/WebVitalsFeature.js';
|
|
6
|
+
import { PerformanceFeature } from './performance/PerformanceFeature.js';
|
|
7
|
+
import { JourneyFeature } from './journey/JourneyFeature.js';
|
|
8
|
+
import { ConsoleFeature } from './console/ConsoleFeature.js';
|
|
9
|
+
import { BugReportFeature } from './bugreport/BugReportFeature.js';
|
|
10
|
+
import { CrashFeature } from './crash/CrashFeature.js';
|
|
11
|
+
import { EngageFeature } from './engage/EngageFeature.js';
|
|
12
|
+
import { InboxFeature } from './inbox/InboxFeature.js';
|
|
13
|
+
import { WebPerfFeature } from './webperf/WebPerfFeature.js';
|
|
14
|
+
import { ProfilerFeature } from './profiler/ProfilerFeature.js';
|
|
15
|
+
import { WatchdogFeature } from './watchdog/WatchdogFeature.js';
|
|
16
|
+
import { ExitIntentFeature } from './exit-intent/ExitIntentFeature.js';
|
|
17
|
+
import { InApp2Feature } from './inapp/InApp2Feature.js';
|
|
18
|
+
import { ReplayFeature } from './replay/ReplayFeature.js';
|
|
19
19
|
/**
|
|
20
20
|
* The feature registry source. Each capture feature vertical (errors, network, webVitals, replay,
|
|
21
21
|
* …) appends its instance here — this is the append-only seam from WEB-SDK-PLAN.md §1. Bootstrap
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* the SDK's own ingestion traffic. Thin shell: interceptors + normalize + stats.
|
|
6
6
|
*/
|
|
7
7
|
import type { IFeature, FeatureContext } from '@scalebun/sdk-contracts';
|
|
8
|
-
import type { NetProtocol, NetFailure } from './types';
|
|
8
|
+
import type { NetProtocol, NetFailure } from './types.js';
|
|
9
9
|
/** Self-observability snapshot (N5) — the SDK's own network-capture health. */
|
|
10
10
|
export interface NetworkStats {
|
|
11
11
|
/** emitted to the pipeline */
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
* taxonomy/slow/route); bodies/headers are off by default (privacy) and an opt-in (N4). Self-excludes
|
|
5
5
|
* the SDK's own ingestion traffic. Thin shell: interceptors + normalize + stats.
|
|
6
6
|
*/
|
|
7
|
-
import { installFetch } from './fetchInterceptor';
|
|
8
|
-
import { installXhr } from './xhrInterceptor';
|
|
9
|
-
import { toNetworkItem } from './normalize';
|
|
10
|
-
import { makeTraceInjector } from './tracing';
|
|
11
|
-
import { DEFAULT_SLOW_MS } from './classify';
|
|
12
|
-
import { ResourceTimingIndex } from './timing';
|
|
13
|
-
import { shouldKeep } from './sampler';
|
|
14
|
-
import { Deduper } from './dedup';
|
|
7
|
+
import { installFetch } from './fetchInterceptor.js';
|
|
8
|
+
import { installXhr } from './xhrInterceptor.js';
|
|
9
|
+
import { toNetworkItem } from './normalize.js';
|
|
10
|
+
import { makeTraceInjector } from './tracing.js';
|
|
11
|
+
import { DEFAULT_SLOW_MS } from './classify.js';
|
|
12
|
+
import { ResourceTimingIndex } from './timing.js';
|
|
13
|
+
import { shouldKeep } from './sampler.js';
|
|
14
|
+
import { Deduper } from './dedup.js';
|
|
15
15
|
function matchUrl(pat, url) {
|
|
16
16
|
return typeof pat === 'string' ? url.includes(pat) : pat.test(url);
|
|
17
17
|
}
|
|
@@ -110,7 +110,7 @@ export class NetworkFeature {
|
|
|
110
110
|
beacon: true,
|
|
111
111
|
};
|
|
112
112
|
const nav = typeof navigator !== 'undefined' ? navigator : undefined;
|
|
113
|
-
void import('./intercept/streams')
|
|
113
|
+
void import('./intercept/streams.js')
|
|
114
114
|
.then((m) => {
|
|
115
115
|
if (this.active)
|
|
116
116
|
this.uninstalls.push(...m.installStreams(window, nav, onRecord, isOwnUrl, flags));
|
|
@@ -152,7 +152,7 @@ export class NetworkFeature {
|
|
|
152
152
|
const wantGraphql = proto === 'http' && c.graphql === undefined && this.maybeGraphql(c);
|
|
153
153
|
const wantBody = !!this.bodyOpts && proto === 'http';
|
|
154
154
|
if (wantGraphql || wantBody) {
|
|
155
|
-
import('./lazy')
|
|
155
|
+
import('./lazy.js')
|
|
156
156
|
.then((m) => m.enrichHttpCapture(c, { graphql: wantGraphql, body: wantBody ? this.bodyOpts : undefined }))
|
|
157
157
|
.catch(() => { })
|
|
158
158
|
.finally(() => {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Stream-safety is guaranteed by the interceptor (it clones the response before the host reads it);
|
|
9
9
|
* here we only consume the already-cloned text. Never throws — capture is best-effort.
|
|
10
10
|
*/
|
|
11
|
-
import type { NetCapture } from '../types';
|
|
11
|
+
import type { NetCapture } from '../types.js';
|
|
12
12
|
export interface BodyCaptureOptions {
|
|
13
13
|
bodyMaxBytes: number;
|
|
14
14
|
contentTypeAllowlist: string[];
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Stream-safety is guaranteed by the interceptor (it clones the response before the host reads it);
|
|
9
9
|
* here we only consume the already-cloned text. Never throws — capture is best-effort.
|
|
10
10
|
*/
|
|
11
|
-
import { scrubText } from '../../../core';
|
|
11
|
+
import { scrubText } from '../../../core/index.js';
|
|
12
12
|
export const DEFAULT_BODY_MAX_BYTES = 8192;
|
|
13
13
|
export const BODY_MAX_CEILING = 64 * 1024; // hard ceiling regardless of config (caps egress)
|
|
14
14
|
export const DEFAULT_CONTENT_TYPES = ['application/json', 'text/plain'];
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* status 0 — we disambiguate by the error message shape (browsers say "Failed to fetch" / mention
|
|
8
8
|
* CORS) but stay conservative: ambiguous → `network_error`.
|
|
9
9
|
*/
|
|
10
|
-
import type { NetFailure } from './types';
|
|
10
|
+
import type { NetFailure } from './types.js';
|
|
11
11
|
export declare const DEFAULT_SLOW_MS = 2000;
|
|
12
12
|
/** Map a settled HTTP request to a failure class, or undefined when it succeeded. */
|
|
13
13
|
export declare function classifyHttp(input: {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* (we never consume the stream) — body capture is a later, opt-in enhancement. Self-excludes the
|
|
4
4
|
* SDK's own ingestion traffic. `target` is injectable so it's unit-testable in node.
|
|
5
5
|
*/
|
|
6
|
-
import type { OnRecord, IsOwnUrl, InjectTrace } from './types';
|
|
6
|
+
import type { OnRecord, IsOwnUrl, InjectTrace } from './types.js';
|
|
7
7
|
type FetchHolder = {
|
|
8
8
|
fetch: typeof fetch;
|
|
9
9
|
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* (we never consume the stream) — body capture is a later, opt-in enhancement. Self-excludes the
|
|
4
4
|
* SDK's own ingestion traffic. `target` is injectable so it's unit-testable in node.
|
|
5
5
|
*/
|
|
6
|
-
import { requestBodyBytes, contentLengthBytes, perfNow } from './size';
|
|
6
|
+
import { requestBodyBytes, contentLengthBytes, perfNow } from './size.js';
|
|
7
7
|
export function installFetch(target, onRecord, isOwnUrl, injectTrace) {
|
|
8
8
|
const original = target.fetch;
|
|
9
9
|
if (typeof original !== 'function')
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* not) synchronously, which we map to a success/failure. Self-excludes the SDK's own egress. Patches
|
|
6
6
|
* `navigator.sendBeacon`; restores on teardown.
|
|
7
7
|
*/
|
|
8
|
-
import type { OnRecord, IsOwnUrl } from '../types';
|
|
8
|
+
import type { OnRecord, IsOwnUrl } from '../types.js';
|
|
9
9
|
type NavHolder = {
|
|
10
10
|
sendBeacon: typeof navigator.sendBeacon;
|
|
11
11
|
};
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* EventSource has no programmatic "close" event — the host calls `.close()`. We patch that to settle,
|
|
8
8
|
* and also settle on a terminal `error` (readyState CLOSED) so a dropped connection still emits.
|
|
9
9
|
*/
|
|
10
|
-
import type { OnRecord, IsOwnUrl } from '../types';
|
|
10
|
+
import type { OnRecord, IsOwnUrl } from '../types.js';
|
|
11
11
|
type EsHolder = {
|
|
12
12
|
EventSource: typeof EventSource;
|
|
13
13
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/** N3/N6 — WebSocket + SSE + sendBeacon installers bundled into ONE lazy chunk (loaded when those
|
|
2
2
|
* transports are tracked). Keeps the long-lived-stream + beacon code out of the core bundle. */
|
|
3
|
-
import { installWebSocket } from './websocket';
|
|
4
|
-
import { installEventSource } from './sse';
|
|
5
|
-
import { installBeacon } from './beacon';
|
|
6
|
-
import type { OnRecord, IsOwnUrl } from '../types';
|
|
3
|
+
import { installWebSocket } from './websocket.js';
|
|
4
|
+
import { installEventSource } from './sse.js';
|
|
5
|
+
import { installBeacon } from './beacon.js';
|
|
6
|
+
import type { OnRecord, IsOwnUrl } from '../types.js';
|
|
7
7
|
export { installWebSocket, installEventSource, installBeacon };
|
|
8
8
|
/**
|
|
9
9
|
* Install all enabled stream transports in one call, returning their uninstallers. Keeps the
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/** N3/N6 — WebSocket + SSE + sendBeacon installers bundled into ONE lazy chunk (loaded when those
|
|
2
2
|
* transports are tracked). Keeps the long-lived-stream + beacon code out of the core bundle. */
|
|
3
|
-
import { installWebSocket } from './websocket';
|
|
4
|
-
import { installEventSource } from './sse';
|
|
5
|
-
import { installBeacon } from './beacon';
|
|
3
|
+
import { installWebSocket } from './websocket.js';
|
|
4
|
+
import { installEventSource } from './sse.js';
|
|
5
|
+
import { installBeacon } from './beacon.js';
|
|
6
6
|
export { installWebSocket, installEventSource, installBeacon };
|
|
7
7
|
/**
|
|
8
8
|
* Install all enabled stream transports in one call, returning their uninstallers. Keeps the
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* (10⁴ messages) stays flat in memory. Patches the global `WebSocket` constructor; restores on
|
|
6
6
|
* teardown. Self-excludes the SDK's own origin (it doesn't open sockets, but defensive).
|
|
7
7
|
*/
|
|
8
|
-
import type { OnRecord, IsOwnUrl } from '../types';
|
|
8
|
+
import type { OnRecord, IsOwnUrl } from '../types.js';
|
|
9
9
|
type WsHolder = {
|
|
10
10
|
WebSocket: typeof WebSocket;
|
|
11
11
|
};
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* GraphQL-looking request, the body capturer when captureBodies is on, WS/SSE installers when those
|
|
5
5
|
* transports are tracked + first used.
|
|
6
6
|
*/
|
|
7
|
-
import { looksLikeGraphql, parseGraphqlRequest, graphqlResponseHasErrors } from './parse/graphql';
|
|
8
|
-
import { type BodyCaptureOptions } from './capture/body';
|
|
9
|
-
import type { NetCapture } from './types';
|
|
7
|
+
import { looksLikeGraphql, parseGraphqlRequest, graphqlResponseHasErrors } from './parse/graphql.js';
|
|
8
|
+
import { type BodyCaptureOptions } from './capture/body.js';
|
|
9
|
+
import type { NetCapture } from './types.js';
|
|
10
10
|
export { looksLikeGraphql, parseGraphqlRequest, graphqlResponseHasErrors };
|
|
11
11
|
export interface HttpEnrichOptions {
|
|
12
12
|
/** Run N2 GraphQL op-awareness (the capture passed the cheap core-side pre-check). */
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* GraphQL-looking request, the body capturer when captureBodies is on, WS/SSE installers when those
|
|
5
5
|
* transports are tracked + first used.
|
|
6
6
|
*/
|
|
7
|
-
import { looksLikeGraphql, parseGraphqlRequest, graphqlResponseHasErrors } from './parse/graphql';
|
|
8
|
-
import { isAllowedContentType, sanitizeBody } from './capture/body';
|
|
7
|
+
import { looksLikeGraphql, parseGraphqlRequest, graphqlResponseHasErrors } from './parse/graphql.js';
|
|
8
|
+
import { isAllowedContentType, sanitizeBody } from './capture/body.js';
|
|
9
9
|
export { looksLikeGraphql, parseGraphqlRequest, graphqlResponseHasErrors };
|
|
10
10
|
/**
|
|
11
11
|
* Single LAZY enrichment pass for an http capture. Reads the (stream-safe, one-shot) response text
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Builds a contract `network` Item from an interceptor capture. */
|
|
2
2
|
import type { NetworkItem } from '@scalebun/protocol';
|
|
3
|
-
import type { NetCapture } from './types';
|
|
3
|
+
import type { NetCapture } from './types.js';
|
|
4
4
|
export interface NormalizeOptions {
|
|
5
5
|
/** "slow" threshold in ms (config.network.slowRequestMs). */
|
|
6
6
|
slowMs?: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Builds a contract `network` Item from an interceptor capture. */
|
|
2
|
-
import { uuid, now } from '../../core';
|
|
3
|
-
import { classifyHttp, isSlow, DEFAULT_SLOW_MS } from './classify';
|
|
4
|
-
import { templateRoute } from './parse/url';
|
|
2
|
+
import { uuid, now } from '../../core/index.js';
|
|
3
|
+
import { classifyHttp, isSlow, DEFAULT_SLOW_MS } from './classify.js';
|
|
4
|
+
import { templateRoute } from './parse/url.js';
|
|
5
5
|
export function toNetworkItem(c, opts = {}) {
|
|
6
6
|
const protocol = c.protocol ?? 'http';
|
|
7
7
|
// WS/SSE/beacon carry their own settle semantics; classify only request/response transports.
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Zero-dep, defensive: never throws (callers feature-detect), bounded work (only the leading bytes of
|
|
8
8
|
* the query are scanned for the operation keyword).
|
|
9
9
|
*/
|
|
10
|
-
import type { NetGraphql } from '../types';
|
|
10
|
+
import type { NetGraphql } from '../types.js';
|
|
11
11
|
/** True when a request looks like GraphQL — URL hint OR a body that parses to a GraphQL op shape. */
|
|
12
12
|
export declare function looksLikeGraphql(url: string, body: string | undefined): boolean;
|
|
13
13
|
/** Parse the request body → operation metadata. Returns undefined when it isn't recognizably GraphQL. */
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* spread evenly and the backend could re-derive it — no client trust, the same hash family as
|
|
6
6
|
* flags/experiments/error-grouping. Zero-dep.
|
|
7
7
|
*/
|
|
8
|
-
import { fnv1a32 } from '../config/bucketing';
|
|
8
|
+
import { fnv1a32 } from '../config/bucketing.js';
|
|
9
9
|
/**
|
|
10
10
|
* Decide whether to keep a request. `sampleRate` ∈ [0,1] is the base for SUCCESSFUL requests; 1 keeps
|
|
11
11
|
* everything (today's behavior), 0 keeps only failed/slow. Out-of-range rates clamp.
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* capture and merges timing onto fetch/XHR (`initiatorType` 'fetch'|'xmlhttprequest'). We only read
|
|
10
10
|
* those initiator types so a resource isn't double-counted by both verticals.
|
|
11
11
|
*/
|
|
12
|
-
import type { NetTiming } from './types';
|
|
12
|
+
import type { NetTiming } from './types.js';
|
|
13
13
|
export interface MergedTiming {
|
|
14
14
|
timing?: NetTiming;
|
|
15
15
|
transferSize?: number;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Bodies/headers are not read in v1. Self-excludes the SDK's own traffic. `target` is injectable
|
|
4
4
|
* for testability.
|
|
5
5
|
*/
|
|
6
|
-
import type { OnRecord, IsOwnUrl, InjectTrace } from './types';
|
|
6
|
+
import type { OnRecord, IsOwnUrl, InjectTrace } from './types.js';
|
|
7
7
|
type XhrHolder = {
|
|
8
8
|
XMLHttpRequest: typeof XMLHttpRequest;
|
|
9
9
|
};
|