svoose 0.1.5 → 0.1.6
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 +46 -11
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +3 -3
- package/dist/metrics/index.d.ts +5 -0
- package/dist/metrics/index.d.ts.map +1 -0
- package/dist/metrics/index.js +2 -0
- package/dist/metrics/index.js.map +7 -0
- package/dist/metrics/metric.d.ts +44 -0
- package/dist/metrics/metric.d.ts.map +1 -0
- package/dist/metrics/metric.js +2 -0
- package/dist/metrics/metric.js.map +7 -0
- package/dist/observe/observe.svelte.d.ts.map +1 -1
- package/dist/observe/observe.svelte.js +1 -1
- package/dist/observe/observe.svelte.js.map +3 -3
- package/dist/observe/sampling.d.ts +2 -20
- package/dist/observe/sampling.d.ts.map +1 -1
- package/dist/observe/sampling.js +1 -1
- package/dist/observe/sampling.js.map +2 -2
- package/dist/observe/session.d.ts +2 -7
- package/dist/observe/session.d.ts.map +1 -1
- package/dist/observe/session.js.map +2 -2
- package/dist/svelte/index.svelte.js +2 -0
- package/dist/svelte/index.svelte.js.map +7 -0
- package/dist/transport/fetch.d.ts +1 -1
- package/dist/transport/fetch.d.ts.map +1 -1
- package/dist/transport/fetch.js +1 -1
- package/dist/transport/fetch.js.map +1 -1
- package/dist/transport/transport.d.ts +2 -10
- package/dist/transport/transport.d.ts.map +1 -1
- package/dist/types/index.d.ts +8 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
> Svelte + Goose = **svoose** — the goose that sees everything
|
|
4
4
|
|
|
5
|
-
Lightweight observability + state machines for Svelte 5. Zero dependencies. Tree-shakeable. **< 5KB gzipped
|
|
5
|
+
Lightweight observability + state machines for Svelte 5. Zero dependencies. Tree-shakeable. **< 5KB gzipped** (core ~3.5KB).
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- **Web Vitals** — CLS, LCP, FID, INP, FCP, TTFB (no external deps)
|
|
10
10
|
- **Error Tracking** — global errors + unhandled rejections
|
|
11
|
+
- **Custom Metrics** — `metric()` for custom analytics events (v0.1.6+)
|
|
12
|
+
- **Session Tracking** — automatic sessionId with timeout (v0.1.5+)
|
|
13
|
+
- **Sampling** — per-event-type rate limiting (v0.1.3+)
|
|
11
14
|
- **State Machines** — minimal FSM with TypeScript inference
|
|
12
15
|
- **Svelte 5 Native** — reactive `useMachine()` hook with $state runes
|
|
13
16
|
- **Tree-shakeable** — pay only for what you use
|
|
@@ -77,9 +80,7 @@ const cleanup = observe({
|
|
|
77
80
|
batchSize: 10,
|
|
78
81
|
flushInterval: 5000,
|
|
79
82
|
|
|
80
|
-
// Sampling (v0.1.3+)
|
|
81
|
-
sampling: 0.1, // 10% of all events
|
|
82
|
-
// or per-event-type (recommended)
|
|
83
|
+
// Sampling (v0.1.3+) — number or per-event-type config
|
|
83
84
|
sampling: {
|
|
84
85
|
vitals: 0.1, // 10% — sufficient for statistics
|
|
85
86
|
errors: 1.0, // 100% — all errors matter
|
|
@@ -87,6 +88,9 @@ const cleanup = observe({
|
|
|
87
88
|
transitions: 0.0, // disabled
|
|
88
89
|
},
|
|
89
90
|
|
|
91
|
+
// Sessions (v0.1.5+)
|
|
92
|
+
session: true, // or { timeout: 30 * 60 * 1000, storage: 'sessionStorage' }
|
|
93
|
+
|
|
90
94
|
// Debug
|
|
91
95
|
debug: false,
|
|
92
96
|
});
|
|
@@ -116,7 +120,6 @@ observe({
|
|
|
116
120
|
errors: 1.0, // 100% — capture all errors
|
|
117
121
|
custom: 0.5, // 50% of custom metrics
|
|
118
122
|
transitions: 0.0, // disabled — no state machine events
|
|
119
|
-
identify: 1.0, // 100% — always track user identification
|
|
120
123
|
},
|
|
121
124
|
});
|
|
122
125
|
```
|
|
@@ -198,6 +201,34 @@ observe({ vitals: ['CLS', 'LCP', 'INP'] });
|
|
|
198
201
|
|
|
199
202
|
> **Note (v0.1.5 breaking change)**: CLS, LCP, and INP now report once per page lifecycle instead of on every update. This matches Chrome DevTools and Google Search Console behavior.
|
|
200
203
|
|
|
204
|
+
#### Custom Metrics (v0.1.6+)
|
|
205
|
+
|
|
206
|
+
Track custom events for analytics:
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
import { metric } from 'svoose';
|
|
210
|
+
|
|
211
|
+
// Basic usage
|
|
212
|
+
metric('checkout_started', { step: 1, cartTotal: 99.99 });
|
|
213
|
+
metric('button_clicked', { id: 'submit-btn' });
|
|
214
|
+
metric('feature_used', { name: 'dark_mode', enabled: true });
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Events are automatically batched with other metrics. You can control the sampling rate:
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
observe({
|
|
221
|
+
endpoint: '/api/metrics',
|
|
222
|
+
sampling: {
|
|
223
|
+
custom: 0.5, // 50% of custom metrics
|
|
224
|
+
vitals: 0.1,
|
|
225
|
+
errors: 1.0,
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**Buffer behavior**: If `metric()` is called before `observe()`, events are buffered (max 100). They're automatically flushed when `observe()` initializes.
|
|
231
|
+
|
|
201
232
|
### `createMachine(config)`
|
|
202
233
|
|
|
203
234
|
Create a state machine.
|
|
@@ -349,12 +380,12 @@ Tree-shakeable — pay only for what you use:
|
|
|
349
380
|
|
|
350
381
|
| Import | Size (gzip) |
|
|
351
382
|
|--------|-------------|
|
|
352
|
-
| `observe()`
|
|
383
|
+
| `observe()` + vitals + errors + metrics | ~3.5 KB |
|
|
353
384
|
| `createMachine()` only | ~0.8 KB |
|
|
354
|
-
| Full bundle (v0.1.x) | ~
|
|
355
|
-
| Full production (v0.2.0+) | ~
|
|
385
|
+
| Full bundle (v0.1.x) | ~4.5 KB |
|
|
386
|
+
| Full production (v0.2.0+) | ~6 KB |
|
|
356
387
|
|
|
357
|
-
> Most apps only need `observe()` core (~
|
|
388
|
+
> Most apps only need `observe()` core (~3.5 KB). Compare: Sentry ~20KB, PostHog ~40KB.
|
|
358
389
|
|
|
359
390
|
## TypeScript
|
|
360
391
|
|
|
@@ -501,8 +532,12 @@ const machine = createMachine({
|
|
|
501
532
|
|
|
502
533
|
- **v0.1.3** ✅ — Sampling (per-event-type rate limiting)
|
|
503
534
|
- **v0.1.4** ✅ — Hotfix (missing sampling.js)
|
|
504
|
-
- **v0.1.5** — Session Tracking + CLS Session Windows fix
|
|
505
|
-
- **v0.1.6
|
|
535
|
+
- **v0.1.5** ✅ — Session Tracking + CLS Session Windows fix
|
|
536
|
+
- **v0.1.6** ✅ — Custom metrics (`metric()` API)
|
|
537
|
+
- **v0.1.7** — Extended Metrics (counter/gauge/histogram + typed API)
|
|
538
|
+
- **v0.1.8** — Beacon + Hybrid Transport
|
|
539
|
+
- **v0.1.9** — Retry Logic
|
|
540
|
+
- **v0.1.10** — Privacy Utilities
|
|
506
541
|
- **v0.2.0** — Production-Ready Observability + Bundle Restructure (modular entry points)
|
|
507
542
|
- **v0.3.0** — SvelteKit Integration (Vite plugin, hooks, route tracking)
|
|
508
543
|
- **v1.0.0** — Stable Release (Q1 2027)
|
package/dist/index.d.ts
CHANGED
|
@@ -15,5 +15,6 @@ export { createFetchTransport, createConsoleTransport } from './transport/index.
|
|
|
15
15
|
export type { Transport, TransportOptions } from './transport/index.js';
|
|
16
16
|
export { createMachine, createEvent } from './machine/index.js';
|
|
17
17
|
export type { MachineConfig, Machine, EventObject, StateNode, TransitionConfig, InferStates, InferEvents, InferContext, } from './machine/index.js';
|
|
18
|
-
export
|
|
18
|
+
export { metric } from './metrics/index.js';
|
|
19
|
+
export type { VitalEvent, TransitionEvent, CustomMetricEvent, ObserveEvent, } from './types/index.js';
|
|
19
20
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAKzD,OAAO,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAKrG,OAAO,EACL,aAAa,EACb,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,iBAAiB,EACjB,UAAU,EACV,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAK5B,OAAO,EACL,UAAU,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,WAAW,EACX,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAK3E,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACpF,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAKxE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EACV,aAAa,EACb,OAAO,EACP,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,YAAY,GACb,MAAM,oBAAoB,CAAC;AAK5B,YAAY,EACV,UAAU,EACV,eAAe,EACf,YAAY,GACb,MAAM,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAKzD,OAAO,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAKrG,OAAO,EACL,aAAa,EACb,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,iBAAiB,EACjB,UAAU,EACV,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAK5B,OAAO,EACL,UAAU,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,WAAW,EACX,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAK3E,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACpF,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAKxE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EACV,aAAa,EACb,OAAO,EACP,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,YAAY,GACb,MAAM,oBAAoB,CAAC;AAK5B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAK5C,YAAY,EACV,UAAU,EACV,eAAe,EACf,iBAAiB,EACjB,YAAY,GACb,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{observe as t}from"./observe/index.js";import{createSampler as n,eventTypeToSamplingType as s}from"./observe/index.js";import{observeErrors as i,registerMachineContext as a,unregisterMachineContext as v}from"./observe/index.js";import{observeCLS as
|
|
1
|
+
import{observe as t}from"./observe/index.js";import{createSampler as n,eventTypeToSamplingType as s}from"./observe/index.js";import{observeErrors as i,registerMachineContext as a,unregisterMachineContext as v}from"./observe/index.js";import{observeCLS as x,observeLCP as f,observeFID as c,observeINP as b,observeFCP as E,observeTTFB as T,vitalObservers as y}from"./observe/index.js";import{createFetchTransport as d,createConsoleTransport as g}from"./transport/index.js";import{createMachine as j,createEvent as M}from"./machine/index.js";import{metric as h}from"./metrics/index.js";export{g as createConsoleTransport,M as createEvent,d as createFetchTransport,j as createMachine,n as createSampler,s as eventTypeToSamplingType,h as metric,t as observe,x as observeCLS,i as observeErrors,E as observeFCP,c as observeFID,b as observeINP,f as observeLCP,T as observeTTFB,a as registerMachineContext,v as unregisterMachineContext,y as vitalObservers};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * \uD83E\uDEBF svoose - Observability + State Machines for Svelte 5\n *\n * @packageDocumentation\n */\n\n// ============================================\n// Core Observability\n// ============================================\nexport { observe } from './observe/index.js';\nexport type { ObserveOptions } from './observe/index.js';\n\n// ============================================\n// Sampling\n// ============================================\nexport { createSampler, eventTypeToSamplingType } from './observe/index.js';\nexport type { SamplingConfig, SamplingOption, SamplingEventType, Sampler } from './observe/index.js';\n\n// ============================================\n// Error Tracking\n// ============================================\nexport {\n observeErrors,\n registerMachineContext,\n unregisterMachineContext,\n} from './observe/index.js';\nexport type {\n ObserveErrorEvent,\n ErrorEvent,\n UnhandledRejectionEvent,\n} from './observe/index.js';\n\n// ============================================\n// Web Vitals\n// ============================================\nexport {\n observeCLS,\n observeLCP,\n observeFID,\n observeINP,\n observeFCP,\n observeTTFB,\n vitalObservers,\n} from './observe/index.js';\nexport type { Metric, MetricName, MetricRating } from './observe/index.js';\n\n// ============================================\n// Transport\n// ============================================\nexport { createFetchTransport, createConsoleTransport } from './transport/index.js';\nexport type { Transport, TransportOptions } from './transport/index.js';\n\n// ============================================\n// State Machines\n// ============================================\nexport { createMachine, createEvent } from './machine/index.js';\nexport type {\n MachineConfig,\n Machine,\n EventObject,\n StateNode,\n TransitionConfig,\n InferStates,\n InferEvents,\n InferContext,\n} from './machine/index.js';\n\n// ============================================\n// Shared Types\n// ============================================\nexport type {\n VitalEvent,\n TransitionEvent,\n ObserveEvent,\n} from './types/index.js';\n"],
|
|
5
|
-
"mappings": "AASA,OAAS,WAAAA,MAAe,qBAMxB,OAAS,iBAAAC,EAAe,2BAAAC,MAA+B,qBAMvD,OACE,iBAAAC,EACA,0BAAAC,EACA,4BAAAC,MACK,qBAUP,OACE,cAAAC,EACA,cAAAC,EACA,cAAAC,EACA,cAAAC,EACA,cAAAC,EACA,eAAAC,EACA,kBAAAC,MACK,qBAMP,OAAS,wBAAAC,EAAsB,0BAAAC,MAA8B,uBAM7D,OAAS,iBAAAC,EAAe,eAAAC,MAAmB",
|
|
6
|
-
"names": ["observe", "createSampler", "eventTypeToSamplingType", "observeErrors", "registerMachineContext", "unregisterMachineContext", "observeCLS", "observeLCP", "observeFID", "observeINP", "observeFCP", "observeTTFB", "vitalObservers", "createFetchTransport", "createConsoleTransport", "createMachine", "createEvent"]
|
|
4
|
+
"sourcesContent": ["/**\n * \uD83E\uDEBF svoose - Observability + State Machines for Svelte 5\n *\n * @packageDocumentation\n */\n\n// ============================================\n// Core Observability\n// ============================================\nexport { observe } from './observe/index.js';\nexport type { ObserveOptions } from './observe/index.js';\n\n// ============================================\n// Sampling\n// ============================================\nexport { createSampler, eventTypeToSamplingType } from './observe/index.js';\nexport type { SamplingConfig, SamplingOption, SamplingEventType, Sampler } from './observe/index.js';\n\n// ============================================\n// Error Tracking\n// ============================================\nexport {\n observeErrors,\n registerMachineContext,\n unregisterMachineContext,\n} from './observe/index.js';\nexport type {\n ObserveErrorEvent,\n ErrorEvent,\n UnhandledRejectionEvent,\n} from './observe/index.js';\n\n// ============================================\n// Web Vitals\n// ============================================\nexport {\n observeCLS,\n observeLCP,\n observeFID,\n observeINP,\n observeFCP,\n observeTTFB,\n vitalObservers,\n} from './observe/index.js';\nexport type { Metric, MetricName, MetricRating } from './observe/index.js';\n\n// ============================================\n// Transport\n// ============================================\nexport { createFetchTransport, createConsoleTransport } from './transport/index.js';\nexport type { Transport, TransportOptions } from './transport/index.js';\n\n// ============================================\n// State Machines\n// ============================================\nexport { createMachine, createEvent } from './machine/index.js';\nexport type {\n MachineConfig,\n Machine,\n EventObject,\n StateNode,\n TransitionConfig,\n InferStates,\n InferEvents,\n InferContext,\n} from './machine/index.js';\n\n// ============================================\n// Custom Metrics\n// ============================================\nexport { metric } from './metrics/index.js';\n\n// ============================================\n// Shared Types\n// ============================================\nexport type {\n VitalEvent,\n TransitionEvent,\n CustomMetricEvent,\n ObserveEvent,\n} from './types/index.js';\n"],
|
|
5
|
+
"mappings": "AASA,OAAS,WAAAA,MAAe,qBAMxB,OAAS,iBAAAC,EAAe,2BAAAC,MAA+B,qBAMvD,OACE,iBAAAC,EACA,0BAAAC,EACA,4BAAAC,MACK,qBAUP,OACE,cAAAC,EACA,cAAAC,EACA,cAAAC,EACA,cAAAC,EACA,cAAAC,EACA,eAAAC,EACA,kBAAAC,MACK,qBAMP,OAAS,wBAAAC,EAAsB,0BAAAC,MAA8B,uBAM7D,OAAS,iBAAAC,EAAe,eAAAC,MAAmB,qBAe3C,OAAS,UAAAC,MAAc",
|
|
6
|
+
"names": ["observe", "createSampler", "eventTypeToSamplingType", "observeErrors", "registerMachineContext", "unregisterMachineContext", "observeCLS", "observeLCP", "observeFID", "observeINP", "observeFCP", "observeTTFB", "vitalObservers", "createFetchTransport", "createConsoleTransport", "createMachine", "createEvent", "metric"]
|
|
7
7
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,MAAM,EACN,gBAAgB,EAChB,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{metric as r,setMetricEmitter as i,getMetricEmitter as n,_getPendingEventsCount as c,_clearPendingEvents as g}from"./metric.js";export{g as _clearPendingEvents,c as _getPendingEventsCount,n as getMetricEmitter,r as metric,i as setMetricEmitter};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/metrics/index.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Metrics module exports\n */\n\nexport {\n metric,\n setMetricEmitter,\n getMetricEmitter,\n _getPendingEventsCount,\n _clearPendingEvents,\n} from './metric.js';\n"],
|
|
5
|
+
"mappings": "AAIA,OACE,UAAAA,EACA,oBAAAC,EACA,oBAAAC,EACA,0BAAAC,EACA,uBAAAC,MACK",
|
|
6
|
+
"names": ["metric", "setMetricEmitter", "getMetricEmitter", "_getPendingEventsCount", "_clearPendingEvents"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom metrics module
|
|
3
|
+
*
|
|
4
|
+
* Provides metric() function for sending custom events with pending buffer support.
|
|
5
|
+
*/
|
|
6
|
+
import type { ObserveEvent } from '../types/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Set the metric emitter function
|
|
9
|
+
* Called by observe() to wire up the metric system
|
|
10
|
+
*
|
|
11
|
+
* @param emit - The emit function from observe(), or null to disconnect
|
|
12
|
+
*/
|
|
13
|
+
export declare function setMetricEmitter(emit: ((event: ObserveEvent) => void) | null): void;
|
|
14
|
+
/**
|
|
15
|
+
* Send a custom metric event
|
|
16
|
+
*
|
|
17
|
+
* Events are automatically batched with other metrics and sent to your backend.
|
|
18
|
+
* If called before observe() is initialized, events are buffered (max 100).
|
|
19
|
+
*
|
|
20
|
+
* @param name - Metric name (e.g., 'checkout_started', 'button_clicked')
|
|
21
|
+
* @param data - Optional data payload
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* metric('checkout_started', { step: 1, cartTotal: 99.99 });
|
|
25
|
+
* metric('button_clicked', { id: 'submit-btn' });
|
|
26
|
+
* metric('feature_used', { name: 'dark_mode', enabled: true });
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* Get the current metric emitter function (for internal use)
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
export declare function getMetricEmitter(): ((event: ObserveEvent) => void) | null;
|
|
33
|
+
export declare function metric(name: string, data?: Record<string, unknown>): void;
|
|
34
|
+
/**
|
|
35
|
+
* Get number of pending events (for testing)
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
export declare function _getPendingEventsCount(): number;
|
|
39
|
+
/**
|
|
40
|
+
* Clear pending events (for testing)
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
export declare function _clearPendingEvents(): void;
|
|
44
|
+
//# sourceMappingURL=metric.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metric.d.ts","sourceRoot":"","sources":["../../src/metrics/metric.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAqB,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAWzE;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,CAUnF;AAED;;;;;;;;;;;;;GAaG;AACH;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,CAAC,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC,GAAG,IAAI,CAEzE;AAkBD,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI,CAuB7E;AAMD;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
let t=null;const e=[];function i(r){if(t=r,t&&e.length>0){const o=e.splice(0,e.length);for(const n of o)t(n)}}function v(){return t}function s(){try{return typeof process<"u",import.meta.env?.DEV===!0}catch{return!1}}function u(r,o={}){const n={type:"custom",name:r,data:o,timestamp:Date.now()};if(t)t(n);else{if(e.length>=100){s()&&console.warn("[svoose] metric() buffer full (100 events). Call observe() to start sending events. New events are being dropped.");return}e.push(n)}}function c(){return e.length}function l(){e.length=0}export{l as _clearPendingEvents,c as _getPendingEventsCount,v as getMetricEmitter,u as metric,i as setMetricEmitter};
|
|
2
|
+
//# sourceMappingURL=metric.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/metrics/metric.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Custom metrics module\n *\n * Provides metric() function for sending custom events with pending buffer support.\n */\n\nimport type { CustomMetricEvent, ObserveEvent } from '../types/index.js';\n\n// Maximum pending events before dropping (with warning in dev)\nconst MAX_PENDING_EVENTS = 100;\n\n// Emitter function set by observe()\nlet emitter: ((event: ObserveEvent) => void) | null = null;\n\n// Pending events buffer for events sent before observe() is initialized\nconst pendingEvents: CustomMetricEvent[] = [];\n\n/**\n * Set the metric emitter function\n * Called by observe() to wire up the metric system\n *\n * @param emit - The emit function from observe(), or null to disconnect\n */\nexport function setMetricEmitter(emit: ((event: ObserveEvent) => void) | null): void {\n emitter = emit;\n\n // Flush pending events when emitter is set\n if (emitter && pendingEvents.length > 0) {\n const events = pendingEvents.splice(0, pendingEvents.length);\n for (const event of events) {\n emitter(event);\n }\n }\n}\n\n/**\n * Send a custom metric event\n *\n * Events are automatically batched with other metrics and sent to your backend.\n * If called before observe() is initialized, events are buffered (max 100).\n *\n * @param name - Metric name (e.g., 'checkout_started', 'button_clicked')\n * @param data - Optional data payload\n *\n * @example\n * metric('checkout_started', { step: 1, cartTotal: 99.99 });\n * metric('button_clicked', { id: 'submit-btn' });\n * metric('feature_used', { name: 'dark_mode', enabled: true });\n */\n/**\n * Get the current metric emitter function (for internal use)\n * @internal\n */\nexport function getMetricEmitter(): ((event: ObserveEvent) => void) | null {\n return emitter;\n}\n\ndeclare const process: { env: Record<string, string | undefined> } | undefined;\n\nfunction isDev(): boolean {\n try {\n if (typeof process !== 'undefined' && process?.env?.NODE_ENV === 'development') {\n return true;\n }\n if ((import.meta as any).env?.DEV === true) {\n return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n\nexport function metric(name: string, data: Record<string, unknown> = {}): void {\n const event: CustomMetricEvent = {\n type: 'custom',\n name,\n data,\n timestamp: Date.now(),\n };\n\n if (emitter) {\n emitter(event);\n } else {\n // Buffer event until observe() is initialized\n if (pendingEvents.length >= MAX_PENDING_EVENTS) {\n if (isDev()) {\n console.warn(\n `[svoose] metric() buffer full (${MAX_PENDING_EVENTS} events). ` +\n `Call observe() to start sending events. New events are being dropped.`\n );\n }\n return;\n }\n pendingEvents.push(event);\n }\n}\n\n// ============================================\n// Test helpers (not exported in production builds)\n// ============================================\n\n/**\n * Get number of pending events (for testing)\n * @internal\n */\nexport function _getPendingEventsCount(): number {\n return pendingEvents.length;\n}\n\n/**\n * Clear pending events (for testing)\n * @internal\n */\nexport function _clearPendingEvents(): void {\n pendingEvents.length = 0;\n}\n"],
|
|
5
|
+
"mappings": "AAYA,IAAIA,EAAkD,KAGtD,MAAMC,EAAqC,CAAC,EAQrC,SAASC,EAAiBC,EAAoD,CAInF,GAHAH,EAAUG,EAGNH,GAAWC,EAAc,OAAS,EAAG,CACvC,MAAMG,EAASH,EAAc,OAAO,EAAGA,EAAc,MAAM,EAC3D,UAAWI,KAASD,EAClBJ,EAAQK,CAAK,CAEjB,CACF,CAoBO,SAASC,GAA2D,CACzE,OAAON,CACT,CAIA,SAASO,GAAiB,CACxB,GAAI,CAIF,OAHI,OAAO,QAAY,IAGlB,YAAoB,KAAK,MAAQ,EAIxC,MAAQ,CACN,MAAO,EACT,CACF,CAEO,SAASC,EAAOC,EAAcC,EAAgC,CAAC,EAAS,CAC7E,MAAML,EAA2B,CAC/B,KAAM,SACN,KAAAI,EACA,KAAAC,EACA,UAAW,KAAK,IAAI,CACtB,EAEA,GAAIV,EACFA,EAAQK,CAAK,MACR,CAEL,GAAIJ,EAAc,QAAU,IAAoB,CAC1CM,EAAM,GACR,QAAQ,KACN,mHAEF,EAEF,MACF,CACAN,EAAc,KAAKI,CAAK,CAC1B,CACF,CAUO,SAASM,GAAiC,CAC/C,OAAOV,EAAc,MACvB,CAMO,SAASW,GAA4B,CAC1CX,EAAc,OAAS,CACzB",
|
|
6
|
+
"names": ["emitter", "pendingEvents", "setMetricEmitter", "emit", "events", "event", "getMetricEmitter", "isDev", "metric", "name", "data", "_getPendingEventsCount", "_clearPendingEvents"]
|
|
7
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observe.svelte.d.ts","sourceRoot":"","sources":["../../src/observe/observe.svelte.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"observe.svelte.d.ts","sourceRoot":"","sources":["../../src/observe/observe.svelte.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH,OAAO,KAAK,EAAE,cAAc,EAAc,YAAY,EAAa,MAAM,mBAAmB,CAAC;AAc7F,QAAA,IAAI,sBAAsB,EAAE,CAAC,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC,GAAG,IAAW,CAAC;AAE1E;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,sBAAsB,GAAG,IAAI,CAE/E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,sBAAsB,CAEjE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,OAAO,CAAC,OAAO,GAAE,cAAmB,GAAG,MAAM,IAAI,CA+KhE;AAED,YAAY,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{vitalObservers as
|
|
1
|
+
import{vitalObservers as y}from"./vitals.js";import{observeErrors as O}from"./errors.js";import{createFetchTransport as E}from"../transport/fetch.js";import{createSampler as S,eventTypeToSamplingType as M}from"./sampling.js";import{createSessionManager as T}from"./session.js";import{setMetricEmitter as f,getMetricEmitter as I}from"../metrics/index.js";const c={endpoint:"/api/observe",vitals:!0,errors:!0,batchSize:10,flushInterval:5e3,sampleRate:1,debug:!1};let b=null;function d(l){b=l}function w(){return b}function N(l={}){if(Math.random()>(l.sampleRate??c.sampleRate))return()=>{};const t={...c,...l},m=t.transport??E(t.endpoint),u=t.sampling!=null?S(t.sampling):null,a=t.session!=null?T(t.session):null,n=[];a&&n.push(()=>a.destroy());const o=[];let v=null;const g=()=>{try{return typeof location<"u"?location.href:""}catch{return""}},s=e=>{if(!(t.filter&&!t.filter(e))){if(u){const r=M(e.type);if(r&&!u.shouldSample(r))return}a&&(e.sessionId=a.getSessionId()),t.debug&&console.log("[svoose]",e),o.push(e),o.length>=t.batchSize&&i()}},i=()=>{if(o.length===0)return;const e=o.splice(0,o.length),r=m.send(e);r&&typeof r.catch=="function"&&r.catch(p=>{t.debug&&console.error("[svoose] transport error:",p)})},h=e=>{const r={type:"vital",name:e.name,value:e.value,rating:e.rating,delta:e.delta,timestamp:e.timestamp,url:g()};s(r)};if(t.vitals){const e=t.vitals===!0?["CLS","LCP","FID","INP","FCP","TTFB"]:t.vitals;for(const r of e){const p=y[r];p&&n.push(p(h))}}if(t.errors&&n.push(O(e=>{s(e)})),d(s),n.push(()=>{w()===s&&d(null)}),f(s),n.push(()=>{I()===s&&f(null)}),v=setInterval(i,t.flushInterval),n.push(()=>{v&&clearInterval(v)}),typeof document<"u"){const e=()=>{document.visibilityState==="hidden"&&i()};document.addEventListener("visibilitychange",e),n.push(()=>{document.removeEventListener("visibilitychange",e)})}if(typeof window<"u"){const e=()=>{i()};window.addEventListener("beforeunload",e),n.push(()=>{window.removeEventListener("beforeunload",e)})}return()=>{i(),n.forEach(e=>e())}}export{w as getGlobalObserver,N as observe,d as setGlobalObserver};
|
|
2
2
|
//# sourceMappingURL=observe.svelte.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/observe/observe.svelte.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Main observe() function - combines vitals, errors, and transport\n */\n\nimport { vitalObservers, type Metric, type MetricName } from './vitals.js';\nimport { observeErrors, type ObserveErrorEvent } from './errors.js';\nimport { createFetchTransport } from '../transport/fetch.js';\nimport {\n createSampler,\n eventTypeToSamplingType,\n type Sampler,\n} from './sampling.js';\nimport { createSessionManager, type SessionManager } from './session.js';\nimport type { ObserveOptions, VitalEvent, ObserveEvent, Transport } from '../types/index.js';\n\n// Default configuration\nconst defaults = {\n endpoint: '/api/observe',\n vitals: true as const,\n errors: true,\n batchSize: 10,\n flushInterval: 5000,\n sampleRate: 1,\n debug: false,\n} satisfies Required<Omit<ObserveOptions, 'transport' | 'filter' | 'sampling' | 'session'>>;\n\n// Global observer callback for state machines\nlet globalObserverCallback: ((event: ObserveEvent) => void) | null = null;\n\n/**\n * Set global observer callback for state machines\n * Called internally to connect machines to observe()\n */\nexport function setGlobalObserver(callback: typeof globalObserverCallback): void {\n globalObserverCallback = callback;\n}\n\n/**\n * Get global observer callback\n * Used by createMachine to send transition events\n */\nexport function getGlobalObserver(): typeof globalObserverCallback {\n return globalObserverCallback;\n}\n\n/**\n * Main observe function - starts collecting metrics and errors\n *\n * @param options - Configuration options\n * @returns Cleanup function to stop observing\n *\n * @example\n * // Basic usage\n * observe();\n *\n * @example\n * // With options\n * observe({\n * endpoint: '/api/metrics',\n * vitals: ['CLS', 'LCP', 'INP'],\n * errors: true,\n * debug: true,\n * });\n */\nexport function observe(options: ObserveOptions = {}): () => void {\n // Legacy sampleRate support (deprecated) - skip entire observer\n if (Math.random() > (options.sampleRate ?? defaults.sampleRate)) {\n return () => {};\n }\n\n const config = { ...defaults, ...options };\n const transport: Transport = config.transport ?? createFetchTransport(config.endpoint);\n\n // Create sampler if sampling option is provided\n const sampler: Sampler | null = config.sampling != null\n ? createSampler(config.sampling)\n : null;\n\n // Create session manager if session option is provided\n const sessionManager: SessionManager | null = config.session != null\n ? createSessionManager(config.session)\n : null;\n\n const cleanups: (() => void)[] = [];\n\n // Cleanup session manager on destroy\n if (sessionManager) {\n cleanups.push(() => sessionManager.destroy());\n }\n const buffer: ObserveEvent[] = [];\n let flushTimer: ReturnType<typeof setInterval> | null = null;\n\n // Get current URL\n const getUrl = (): string => {\n try {\n return typeof location !== 'undefined' ? location.href : '';\n } catch {\n return '';\n }\n };\n\n // Buffer an event and potentially flush\n const bufferEvent = (event: ObserveEvent): void => {\n // Apply filter if provided\n if (config.filter && !config.filter(event)) {\n return;\n }\n\n // Apply per-event-type sampling\n if (sampler) {\n const samplingType = eventTypeToSamplingType(event.type);\n if (samplingType && !sampler.shouldSample(samplingType)) {\n return;\n }\n }\n\n // Add sessionId if session manager is enabled\n if (sessionManager) {\n (event as ObserveEvent & { sessionId?: string }).sessionId = sessionManager.getSessionId();\n }\n\n if (config.debug) {\n console.log('[svoose]', event);\n }\n\n buffer.push(event);\n\n if (buffer.length >= config.batchSize) {\n flush();\n }\n };\n\n // Send buffered events to transport\n const flush = (): void => {\n if (buffer.length === 0) return;\n\n const events = buffer.splice(0, buffer.length);\n // Handle both Promise and non-Promise returns from transport.send()\n const result = transport.send(events);\n if (result && typeof result.catch === 'function') {\n result.catch((err) => {\n if (config.debug) {\n console.error('[svoose] transport error:', err);\n }\n });\n }\n };\n\n // Convert metric to vital event\n const handleMetric = (metric: Metric): void => {\n const vitalEvent: VitalEvent = {\n type: 'vital',\n name: metric.name,\n value: metric.value,\n rating: metric.rating,\n delta: metric.delta,\n timestamp: metric.timestamp,\n url: getUrl(),\n };\n bufferEvent(vitalEvent);\n };\n\n // Setup vitals observers\n if (config.vitals) {\n const vitalsToObserve: MetricName[] =\n config.vitals === true\n ? ['CLS', 'LCP', 'FID', 'INP', 'FCP', 'TTFB']\n : config.vitals;\n\n for (const name of vitalsToObserve) {\n const observer = vitalObservers[name];\n if (observer) {\n cleanups.push(observer(handleMetric));\n }\n }\n }\n\n // Setup error observer\n if (config.errors) {\n cleanups.push(\n observeErrors((event: ObserveErrorEvent) => {\n bufferEvent(event);\n })\n );\n }\n\n // Setup global observer for state machines\n setGlobalObserver(bufferEvent);\n cleanups.push(() => setGlobalObserver(null));\n\n // Setup flush interval\n flushTimer = setInterval(flush, config.flushInterval);\n cleanups.push(() => {\n if (flushTimer) clearInterval(flushTimer);\n });\n\n // Flush on page visibility change (user navigating away)\n if (typeof document !== 'undefined') {\n const visibilityHandler = (): void => {\n if (document.visibilityState === 'hidden') {\n flush();\n }\n };\n document.addEventListener('visibilitychange', visibilityHandler);\n cleanups.push(() => {\n document.removeEventListener('visibilitychange', visibilityHandler);\n });\n }\n\n // Flush on beforeunload\n if (typeof window !== 'undefined') {\n const unloadHandler = (): void => {\n flush();\n };\n window.addEventListener('beforeunload', unloadHandler);\n cleanups.push(() => {\n window.removeEventListener('beforeunload', unloadHandler);\n });\n }\n\n // Return cleanup function\n return () => {\n flush();\n cleanups.forEach((fn) => fn());\n };\n}\n\nexport type { ObserveOptions };\n"],
|
|
5
|
-
"mappings": "AAIA,OAAS,kBAAAA,MAAoD,cAC7D,OAAS,iBAAAC,MAA6C,cACtD,OAAS,wBAAAC,MAA4B,wBACrC,OACE,iBAAAC,EACA,2BAAAC,MAEK,gBACP,OAAS,wBAAAC,MAAiD,
|
|
6
|
-
"names": ["vitalObservers", "observeErrors", "createFetchTransport", "createSampler", "eventTypeToSamplingType", "createSessionManager", "defaults", "globalObserverCallback", "setGlobalObserver", "callback", "getGlobalObserver", "observe", "options", "config", "transport", "sampler", "sessionManager", "cleanups", "buffer", "flushTimer", "getUrl", "bufferEvent", "event", "samplingType", "flush", "events", "result", "err", "handleMetric", "metric", "vitalEvent", "vitalsToObserve", "name", "observer", "visibilityHandler", "unloadHandler", "fn"]
|
|
4
|
+
"sourcesContent": ["/**\n * Main observe() function - combines vitals, errors, and transport\n */\n\nimport { vitalObservers, type Metric, type MetricName } from './vitals.js';\nimport { observeErrors, type ObserveErrorEvent } from './errors.js';\nimport { createFetchTransport } from '../transport/fetch.js';\nimport {\n createSampler,\n eventTypeToSamplingType,\n type Sampler,\n} from './sampling.js';\nimport { createSessionManager, type SessionManager } from './session.js';\nimport { setMetricEmitter, getMetricEmitter } from '../metrics/index.js';\nimport type { ObserveOptions, VitalEvent, ObserveEvent, Transport } from '../types/index.js';\n\n// Default configuration\nconst defaults = {\n endpoint: '/api/observe',\n vitals: true as const,\n errors: true,\n batchSize: 10,\n flushInterval: 5000,\n sampleRate: 1,\n debug: false,\n} satisfies Required<Omit<ObserveOptions, 'transport' | 'filter' | 'sampling' | 'session'>>;\n\n// Global observer callback for state machines\nlet globalObserverCallback: ((event: ObserveEvent) => void) | null = null;\n\n/**\n * Set global observer callback for state machines\n * Called internally to connect machines to observe()\n */\nexport function setGlobalObserver(callback: typeof globalObserverCallback): void {\n globalObserverCallback = callback;\n}\n\n/**\n * Get global observer callback\n * Used by createMachine to send transition events\n */\nexport function getGlobalObserver(): typeof globalObserverCallback {\n return globalObserverCallback;\n}\n\n/**\n * Main observe function - starts collecting metrics and errors\n *\n * @param options - Configuration options\n * @returns Cleanup function to stop observing\n *\n * @example\n * // Basic usage\n * observe();\n *\n * @example\n * // With options\n * observe({\n * endpoint: '/api/metrics',\n * vitals: ['CLS', 'LCP', 'INP'],\n * errors: true,\n * debug: true,\n * });\n */\nexport function observe(options: ObserveOptions = {}): () => void {\n // Legacy sampleRate support (deprecated) - skip entire observer\n if (Math.random() > (options.sampleRate ?? defaults.sampleRate)) {\n return () => {};\n }\n\n const config = { ...defaults, ...options };\n const transport: Transport = config.transport ?? createFetchTransport(config.endpoint);\n\n // Create sampler if sampling option is provided\n const sampler: Sampler | null = config.sampling != null\n ? createSampler(config.sampling)\n : null;\n\n // Create session manager if session option is provided\n const sessionManager: SessionManager | null = config.session != null\n ? createSessionManager(config.session)\n : null;\n\n const cleanups: (() => void)[] = [];\n\n // Cleanup session manager on destroy\n if (sessionManager) {\n cleanups.push(() => sessionManager.destroy());\n }\n const buffer: ObserveEvent[] = [];\n let flushTimer: ReturnType<typeof setInterval> | null = null;\n\n // Get current URL\n const getUrl = (): string => {\n try {\n return typeof location !== 'undefined' ? location.href : '';\n } catch {\n return '';\n }\n };\n\n // Buffer an event and potentially flush\n const bufferEvent = (event: ObserveEvent): void => {\n // Apply filter if provided\n if (config.filter && !config.filter(event)) {\n return;\n }\n\n // Apply per-event-type sampling\n if (sampler) {\n const samplingType = eventTypeToSamplingType(event.type);\n if (samplingType && !sampler.shouldSample(samplingType)) {\n return;\n }\n }\n\n // Add sessionId if session manager is enabled\n if (sessionManager) {\n (event as ObserveEvent & { sessionId?: string }).sessionId = sessionManager.getSessionId();\n }\n\n if (config.debug) {\n console.log('[svoose]', event);\n }\n\n buffer.push(event);\n\n if (buffer.length >= config.batchSize) {\n flush();\n }\n };\n\n // Send buffered events to transport\n const flush = (): void => {\n if (buffer.length === 0) return;\n\n const events = buffer.splice(0, buffer.length);\n // Handle both Promise and non-Promise returns from transport.send()\n const result = transport.send(events);\n if (result && typeof result.catch === 'function') {\n result.catch((err) => {\n if (config.debug) {\n console.error('[svoose] transport error:', err);\n }\n });\n }\n };\n\n // Convert metric to vital event\n const handleMetric = (metric: Metric): void => {\n const vitalEvent: VitalEvent = {\n type: 'vital',\n name: metric.name,\n value: metric.value,\n rating: metric.rating,\n delta: metric.delta,\n timestamp: metric.timestamp,\n url: getUrl(),\n };\n bufferEvent(vitalEvent);\n };\n\n // Setup vitals observers\n if (config.vitals) {\n const vitalsToObserve: MetricName[] =\n config.vitals === true\n ? ['CLS', 'LCP', 'FID', 'INP', 'FCP', 'TTFB']\n : config.vitals;\n\n for (const name of vitalsToObserve) {\n const observer = vitalObservers[name];\n if (observer) {\n cleanups.push(observer(handleMetric));\n }\n }\n }\n\n // Setup error observer\n if (config.errors) {\n cleanups.push(\n observeErrors((event: ObserveErrorEvent) => {\n bufferEvent(event);\n })\n );\n }\n\n // Setup global observer for state machines\n setGlobalObserver(bufferEvent);\n cleanups.push(() => {\n // Only clear if we're still the active observer\n if (getGlobalObserver() === bufferEvent) {\n setGlobalObserver(null);\n }\n });\n\n // Setup metric emitter for custom metrics\n setMetricEmitter(bufferEvent);\n cleanups.push(() => {\n // Only clear if we're still the active emitter\n if (getMetricEmitter() === bufferEvent) {\n setMetricEmitter(null);\n }\n });\n\n // Setup flush interval\n flushTimer = setInterval(flush, config.flushInterval);\n cleanups.push(() => {\n if (flushTimer) clearInterval(flushTimer);\n });\n\n // Flush on page visibility change (user navigating away)\n if (typeof document !== 'undefined') {\n const visibilityHandler = (): void => {\n if (document.visibilityState === 'hidden') {\n flush();\n }\n };\n document.addEventListener('visibilitychange', visibilityHandler);\n cleanups.push(() => {\n document.removeEventListener('visibilitychange', visibilityHandler);\n });\n }\n\n // Flush on beforeunload\n if (typeof window !== 'undefined') {\n const unloadHandler = (): void => {\n flush();\n };\n window.addEventListener('beforeunload', unloadHandler);\n cleanups.push(() => {\n window.removeEventListener('beforeunload', unloadHandler);\n });\n }\n\n // Return cleanup function\n return () => {\n flush();\n cleanups.forEach((fn) => fn());\n };\n}\n\nexport type { ObserveOptions };\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["vitalObservers", "observeErrors", "createFetchTransport", "createSampler", "eventTypeToSamplingType", "createSessionManager", "setMetricEmitter", "getMetricEmitter", "defaults", "globalObserverCallback", "setGlobalObserver", "callback", "getGlobalObserver", "observe", "options", "config", "transport", "sampler", "sessionManager", "cleanups", "buffer", "flushTimer", "getUrl", "bufferEvent", "event", "samplingType", "flush", "events", "result", "err", "handleMetric", "metric", "vitalEvent", "vitalsToObserve", "name", "observer", "visibilityHandler", "unloadHandler", "fn"]
|
|
7
7
|
}
|
|
@@ -1,26 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Sampling utilities for rate limiting events by type
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* Each rate is a number between 0 and 1 (0 = disabled, 1 = all)
|
|
7
|
-
*/
|
|
8
|
-
export interface SamplingConfig {
|
|
9
|
-
/** Sampling rate for Web Vitals events (default: 1) */
|
|
10
|
-
vitals?: number;
|
|
11
|
-
/** Sampling rate for error events (default: 1) */
|
|
12
|
-
errors?: number;
|
|
13
|
-
/** Sampling rate for custom metric events (default: 1) */
|
|
14
|
-
custom?: number;
|
|
15
|
-
/** Sampling rate for state machine transition events (default: 1) */
|
|
16
|
-
transitions?: number;
|
|
17
|
-
/** Sampling rate for identify events (default: 1) */
|
|
18
|
-
identify?: number;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Sampling option - either a single rate for all events or per-type config
|
|
22
|
-
*/
|
|
23
|
-
export type SamplingOption = number | SamplingConfig;
|
|
4
|
+
import type { SamplingConfig, SamplingOption } from '../types/index.js';
|
|
5
|
+
export type { SamplingConfig, SamplingOption };
|
|
24
6
|
/**
|
|
25
7
|
* Event types that can be sampled
|
|
26
8
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sampling.d.ts","sourceRoot":"","sources":["../../src/observe/sampling.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"sampling.d.ts","sourceRoot":"","sources":["../../src/observe/sampling.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,cAAc,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB;;;;OAIG;IACH,YAAY,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAEpD;;;;OAIG;IACH,OAAO,CAAC,SAAS,EAAE,iBAAiB,GAAG,MAAM,CAAC;CAC/C;AAWD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAmC7D;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,GAChB,iBAAiB,GAAG,IAAI,CAgB1B"}
|
package/dist/observe/sampling.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function t(e){return e<=0?0:e>=1?1:e}function a(e){const i=typeof e=="number"?{vitals:t(e),errors:t(e),custom:t(e),transitions:t(e),identify:1}:{vitals:t(e.vitals??1),errors:t(e.errors??1),custom:t(e.custom??1),transitions:t(e.transitions??1),identify:t(e.identify??1)};return{shouldSample(n){const r=i[n];return r>=1?!0:r<=0?!1:Math.random()<r},getRate(n){return i[n]}}}function
|
|
1
|
+
function t(e){return e<=0?0:e>=1?1:e}function a(e){const i=typeof e=="number"?{vitals:t(e),errors:t(e),custom:t(e),transitions:t(e),identify:1}:{vitals:t(e.vitals??1),errors:t(e.errors??1),custom:t(e.custom??1),transitions:t(e.transitions??1),identify:t(e.identify??1)};return{shouldSample(n){const r=i[n];return r>=1?!0:r<=0?!1:Math.random()<r},getRate(n){return i[n]}}}function p(e){switch(e){case"vital":return"vitals";case"error":case"unhandled-rejection":return"errors";case"custom":return"custom";case"transition":return"transitions";case"identify":return"identify";default:return null}}export{a as createSampler,p as eventTypeToSamplingType};
|
|
2
2
|
//# sourceMappingURL=sampling.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/observe/sampling.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Sampling utilities for rate limiting events by type\n */\n\
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/**\n * Sampling utilities for rate limiting events by type\n */\n\nimport type { SamplingConfig, SamplingOption } from '../types/index.js';\n\n// Re-export types from canonical source\nexport type { SamplingConfig, SamplingOption };\n\n/**\n * Event types that can be sampled\n */\nexport type SamplingEventType = keyof SamplingConfig;\n\n/**\n * Sampler interface returned by createSampler\n */\nexport interface Sampler {\n /**\n * Check if an event should be sampled (included)\n * @param eventType - The type of event\n * @returns true if the event should be included, false if dropped\n */\n shouldSample(eventType: SamplingEventType): boolean;\n\n /**\n * Get the sampling rate for an event type\n * @param eventType - The type of event\n * @returns The rate (0-1)\n */\n getRate(eventType: SamplingEventType): number;\n}\n\n/**\n * Normalize a sampling rate to be between 0 and 1\n */\nfunction normalizeRate(rate: number): number {\n if (rate <= 0) return 0;\n if (rate >= 1) return 1;\n return rate;\n}\n\n/**\n * Create a sampler instance for filtering events by sampling rate\n *\n * @param config - Sampling configuration (number or per-type config)\n * @returns Sampler instance\n *\n * @example\n * // Simple - same rate for all events\n * const sampler = createSampler(0.1); // 10% of all events\n *\n * @example\n * // Per-event-type rates\n * const sampler = createSampler({\n * vitals: 0.1, // 10% of vitals\n * errors: 1.0, // 100% of errors\n * custom: 0.5, // 50% of custom metrics\n * transitions: 0.0, // disabled\n * });\n */\nexport function createSampler(config: SamplingOption): Sampler {\n // Build rates object with defaults\n const rates: Required<SamplingConfig> =\n typeof config === 'number'\n ? {\n vitals: normalizeRate(config),\n errors: normalizeRate(config),\n custom: normalizeRate(config),\n transitions: normalizeRate(config),\n identify: 1, // Always send identify events by default\n }\n : {\n vitals: normalizeRate(config.vitals ?? 1),\n errors: normalizeRate(config.errors ?? 1),\n custom: normalizeRate(config.custom ?? 1),\n transitions: normalizeRate(config.transitions ?? 1),\n identify: normalizeRate(config.identify ?? 1),\n };\n\n return {\n shouldSample(eventType: SamplingEventType): boolean {\n const rate = rates[eventType];\n\n // Fast paths\n if (rate >= 1) return true;\n if (rate <= 0) return false;\n\n // Random sampling\n return Math.random() < rate;\n },\n\n getRate(eventType: SamplingEventType): number {\n return rates[eventType];\n },\n };\n}\n\n/**\n * Map ObserveEvent.type to SamplingEventType\n */\nexport function eventTypeToSamplingType(\n eventType: string\n): SamplingEventType | null {\n switch (eventType) {\n case 'vital':\n return 'vitals';\n case 'error':\n case 'unhandled-rejection':\n return 'errors';\n case 'custom':\n return 'custom';\n case 'transition':\n return 'transitions';\n case 'identify':\n return 'identify';\n default:\n return null;\n }\n}\n"],
|
|
5
|
+
"mappings": "AAoCA,SAASA,EAAcC,EAAsB,CAC3C,OAAIA,GAAQ,EAAU,EAClBA,GAAQ,EAAU,EACfA,CACT,CAqBO,SAASC,EAAcC,EAAiC,CAE7D,MAAMC,EACJ,OAAOD,GAAW,SACd,CACE,OAAQH,EAAcG,CAAM,EAC5B,OAAQH,EAAcG,CAAM,EAC5B,OAAQH,EAAcG,CAAM,EAC5B,YAAaH,EAAcG,CAAM,EACjC,SAAU,CACZ,EACA,CACE,OAAQH,EAAcG,EAAO,QAAU,CAAC,EACxC,OAAQH,EAAcG,EAAO,QAAU,CAAC,EACxC,OAAQH,EAAcG,EAAO,QAAU,CAAC,EACxC,YAAaH,EAAcG,EAAO,aAAe,CAAC,EAClD,SAAUH,EAAcG,EAAO,UAAY,CAAC,CAC9C,EAEN,MAAO,CACL,aAAaE,EAAuC,CAClD,MAAMJ,EAAOG,EAAMC,CAAS,EAG5B,OAAIJ,GAAQ,EAAU,GAClBA,GAAQ,EAAU,GAGf,KAAK,OAAO,EAAIA,CACzB,EAEA,QAAQI,EAAsC,CAC5C,OAAOD,EAAMC,CAAS,CACxB,CACF,CACF,CAKO,SAASC,EACdD,EAC0B,CAC1B,OAAQA,EAAW,CACjB,IAAK,QACH,MAAO,SACT,IAAK,QACL,IAAK,sBACH,MAAO,SACT,IAAK,SACH,MAAO,SACT,IAAK,aACH,MAAO,cACT,IAAK,WACH,MAAO,WACT,QACE,OAAO,IACX,CACF",
|
|
6
6
|
"names": ["normalizeRate", "rate", "createSampler", "config", "rates", "eventType", "eventTypeToSamplingType"]
|
|
7
7
|
}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Session Tracking - automatic sessionId generation with timeout
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
timeout: number;
|
|
7
|
-
/** Storage type for session persistence */
|
|
8
|
-
storage: 'sessionStorage' | 'localStorage' | 'memory';
|
|
9
|
-
}
|
|
10
|
-
export type SessionOption = boolean | Partial<SessionConfig>;
|
|
4
|
+
import type { SessionConfig, SessionOption } from '../types/index.js';
|
|
5
|
+
export type { SessionConfig, SessionOption };
|
|
11
6
|
export interface SessionManager {
|
|
12
7
|
/** Get current session ID (creates new session if expired) */
|
|
13
8
|
getSessionId: () => string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/observe/session.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/observe/session.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGtE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,CAAC;AAW7C,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,YAAY,EAAE,MAAM,MAAM,CAAC;IAC3B,iCAAiC;IACjC,KAAK,EAAE,MAAM,MAAM,CAAC;IACpB,gDAAgD;IAChD,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAYD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,GAAG,cAAc,GAAG,IAAI,CAuIjF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/observe/session.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Session Tracking - automatic sessionId generation with timeout\n */\n\
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/**\n * Session Tracking - automatic sessionId generation with timeout\n */\n\nimport type { SessionConfig, SessionOption } from '../types/index.js';\n\n// Re-export types from canonical source\nexport type { SessionConfig, SessionOption };\n\ninterface Session {\n id: string;\n startedAt: number;\n lastActivity: number;\n}\n\nconst DEFAULT_TIMEOUT = 30 * 60 * 1000; // 30 minutes\nconst STORAGE_KEY = 'svoose_session';\n\nexport interface SessionManager {\n /** Get current session ID (creates new session if expired) */\n getSessionId: () => string;\n /** Force create a new session */\n reset: () => string;\n /** Destroy session manager and clear storage */\n destroy: () => void;\n}\n\n/**\n * Generate a unique session ID\n * Format: timestamp-randomString (e.g., \"1706123456789-abc123def\")\n */\nfunction generateId(): string {\n const timestamp = Date.now();\n const random = Math.random().toString(36).slice(2, 11);\n return `${timestamp}-${random}`;\n}\n\n/**\n * Create a session manager\n *\n * @param config - Session configuration (true = defaults, false = disabled)\n * @returns SessionManager or null if disabled\n *\n * @example\n * // Enable with defaults\n * const session = createSessionManager(true);\n * session?.getSessionId(); // \"1706123456789-abc123def\"\n *\n * @example\n * // Custom config\n * const session = createSessionManager({\n * timeout: 60 * 60 * 1000, // 1 hour\n * storage: 'localStorage',\n * });\n */\nexport function createSessionManager(config: SessionOption): SessionManager | null {\n // Disabled\n if (config === false) return null;\n\n // Normalize config\n const opts: SessionConfig = config === true\n ? { timeout: DEFAULT_TIMEOUT, storage: 'sessionStorage' }\n : {\n timeout: config.timeout ?? DEFAULT_TIMEOUT,\n storage: config.storage ?? 'sessionStorage',\n };\n\n let currentSession: Session | null = null;\n\n /**\n * Get storage instance (with SSR and private mode safety)\n */\n function getStorage(): Storage | null {\n if (opts.storage === 'memory') return null;\n if (typeof window === 'undefined') return null;\n\n try {\n const storage = opts.storage === 'localStorage' ? localStorage : sessionStorage;\n // Test if storage is available (throws in private mode on some browsers)\n const testKey = '__svoose_test__';\n storage.setItem(testKey, '1');\n storage.removeItem(testKey);\n return storage;\n } catch {\n return null;\n }\n }\n\n /**\n * Load session from storage\n */\n function load(): Session | null {\n const storage = getStorage();\n if (!storage) return null;\n\n try {\n const data = storage.getItem(STORAGE_KEY);\n if (!data) return null;\n\n const session = JSON.parse(data) as Session;\n\n // Validate session structure\n if (\n typeof session.id !== 'string' ||\n typeof session.startedAt !== 'number' ||\n typeof session.lastActivity !== 'number'\n ) {\n return null;\n }\n\n return session;\n } catch {\n return null;\n }\n }\n\n /**\n * Save session to storage\n */\n function save(session: Session): void {\n const storage = getStorage();\n if (!storage) return;\n\n try {\n storage.setItem(STORAGE_KEY, JSON.stringify(session));\n } catch {\n // Quota exceeded - fail silently\n }\n }\n\n /**\n * Create a new session\n */\n function createNew(): Session {\n const now = Date.now();\n const session: Session = {\n id: generateId(),\n startedAt: now,\n lastActivity: now,\n };\n save(session);\n return session;\n }\n\n /**\n * Check if session is expired\n */\n function isExpired(session: Session): boolean {\n const now = Date.now();\n return now - session.lastActivity > opts.timeout;\n }\n\n return {\n getSessionId(): string {\n const now = Date.now();\n\n // Try to load from storage if not in memory\n if (!currentSession) {\n currentSession = load();\n }\n\n // Create new session if none exists or expired\n if (!currentSession || isExpired(currentSession)) {\n currentSession = createNew();\n return currentSession.id;\n }\n\n // Update last activity\n currentSession.lastActivity = now;\n save(currentSession);\n return currentSession.id;\n },\n\n reset(): string {\n currentSession = createNew();\n return currentSession.id;\n },\n\n destroy(): void {\n currentSession = null;\n const storage = getStorage();\n if (storage) {\n try {\n storage.removeItem(STORAGE_KEY);\n } catch {\n // Ignore errors\n }\n }\n },\n };\n}\n"],
|
|
5
|
+
"mappings": "AAgBA,MAAMA,EAAc,iBAepB,SAASC,GAAqB,CAC5B,MAAMC,EAAY,KAAK,IAAI,EACrBC,EAAS,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,EAAG,EAAE,EACrD,MAAO,GAAGD,CAAS,IAAIC,CAAM,EAC/B,CAoBO,SAASC,EAAqBC,EAA8C,CAEjF,GAAIA,IAAW,GAAO,OAAO,KAG7B,MAAMC,EAAsBD,IAAW,GACnC,CAAE,QAAS,KAAiB,QAAS,gBAAiB,EACtD,CACE,QAASA,EAAO,SAAW,KAC3B,QAASA,EAAO,SAAW,gBAC7B,EAEJ,IAAIE,EAAiC,KAKrC,SAASC,GAA6B,CAEpC,GADIF,EAAK,UAAY,UACjB,OAAO,OAAW,IAAa,OAAO,KAE1C,GAAI,CACF,MAAMG,EAAUH,EAAK,UAAY,eAAiB,aAAe,eAE3DI,EAAU,kBAChB,OAAAD,EAAQ,QAAQC,EAAS,GAAG,EAC5BD,EAAQ,WAAWC,CAAO,EACnBD,CACT,MAAQ,CACN,OAAO,IACT,CACF,CAKA,SAASE,GAAuB,CAC9B,MAAMF,EAAUD,EAAW,EAC3B,GAAI,CAACC,EAAS,OAAO,KAErB,GAAI,CACF,MAAMG,EAAOH,EAAQ,QAAQT,CAAW,EACxC,GAAI,CAACY,EAAM,OAAO,KAElB,MAAMC,EAAU,KAAK,MAAMD,CAAI,EAG/B,OACE,OAAOC,EAAQ,IAAO,UACtB,OAAOA,EAAQ,WAAc,UAC7B,OAAOA,EAAQ,cAAiB,SAEzB,KAGFA,CACT,MAAQ,CACN,OAAO,IACT,CACF,CAKA,SAASC,EAAKD,EAAwB,CACpC,MAAMJ,EAAUD,EAAW,EAC3B,GAAKC,EAEL,GAAI,CACFA,EAAQ,QAAQT,EAAa,KAAK,UAAUa,CAAO,CAAC,CACtD,MAAQ,CAER,CACF,CAKA,SAASE,GAAqB,CAC5B,MAAMC,EAAM,KAAK,IAAI,EACfH,EAAmB,CACvB,GAAIZ,EAAW,EACf,UAAWe,EACX,aAAcA,CAChB,EACA,OAAAF,EAAKD,CAAO,EACLA,CACT,CAKA,SAASI,EAAUJ,EAA2B,CAE5C,OADY,KAAK,IAAI,EACRA,EAAQ,aAAeP,EAAK,OAC3C,CAEA,MAAO,CACL,cAAuB,CACrB,MAAMU,EAAM,KAAK,IAAI,EAQrB,OALKT,IACHA,EAAiBI,EAAK,GAIpB,CAACJ,GAAkBU,EAAUV,CAAc,GAC7CA,EAAiBQ,EAAU,EACpBR,EAAe,KAIxBA,EAAe,aAAeS,EAC9BF,EAAKP,CAAc,EACZA,EAAe,GACxB,EAEA,OAAgB,CACd,OAAAA,EAAiBQ,EAAU,EACpBR,EAAe,EACxB,EAEA,SAAgB,CACdA,EAAiB,KACjB,MAAME,EAAUD,EAAW,EAC3B,GAAIC,EACF,GAAI,CACFA,EAAQ,WAAWT,CAAW,CAChC,MAAQ,CAER,CAEJ,CACF,CACF",
|
|
6
6
|
"names": ["STORAGE_KEY", "generateId", "timestamp", "random", "createSessionManager", "config", "opts", "currentSession", "getStorage", "storage", "testKey", "load", "data", "session", "save", "createNew", "now", "isExpired"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createMachine as r}from"../machine/index.js";function s(o){const e=r(o);let n=$state(e.state),a=$state(e.context);const c=e.send.bind(e);return{get state(){return n},get context(){return a},matches(t){return n===t},matchesAny(...t){return t.includes(n)},can(t){return e.can(t)},send:t=>{c(t),n=e.state,a=e.context},destroy:e.destroy.bind(e)}}const v=s;export{v as fromMachine,s as useMachine};
|
|
2
|
+
//# sourceMappingURL=index.svelte.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/svelte/index.svelte.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Svelte 5 specific utilities for svoose\n *\n * Provides reactive wrappers and hooks for state machines\n */\n\n/// <reference path=\"./runes.d.ts\" />\n\nimport { createMachine, type MachineConfig, type EventObject } from '../machine/index.js';\n\n/**\n * Reactive machine state for Svelte 5 components\n */\nexport interface ReactiveMachine<\n TContext extends object,\n TState extends string,\n TEvent extends EventObject\n> {\n /** Current state (reactive - triggers re-render on change) */\n readonly state: TState;\n /** Current context (reactive - triggers re-render on change) */\n readonly context: TContext;\n /** Check if machine is in given state */\n matches(state: TState): boolean;\n /** Check if machine is in any of given states */\n matchesAny(...states: TState[]): boolean;\n /** Check if event can be sent */\n can(eventType: TEvent['type']): boolean;\n /** Send event to machine */\n send(event: TEvent | TEvent['type']): void;\n /** Cleanup machine */\n destroy(): void;\n}\n\n/**\n * Create a reactive state machine for Svelte 5 components\n *\n * This is the recommended way to use svoose in Svelte 5 components.\n * The returned machine's state and context are automatically reactive\n * and will trigger component re-renders when they change.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { useMachine } from 'svoose/svelte';\n *\n * const toggle = useMachine({\n * id: 'toggle',\n * initial: 'off',\n * states: {\n * off: { on: { TOGGLE: 'on' } },\n * on: { on: { TOGGLE: 'off' } },\n * },\n * });\n * </script>\n *\n * <button onclick={() => toggle.send('TOGGLE')}>\n * {toggle.state}\n * </button>\n * ```\n */\nexport function useMachine<\n TContext extends object,\n TState extends string,\n TEvent extends EventObject\n>(config: MachineConfig<TContext, TState, TEvent>): ReactiveMachine<TContext, TState, TEvent> {\n // Create base machine\n const machine = createMachine(config);\n\n // Reactive state using Svelte 5 $state rune\n let reactiveState = $state<TState>(machine.state);\n let reactiveContext = $state<TContext>(machine.context);\n\n // Wrap send to update reactive state\n const originalSend = machine.send.bind(machine);\n\n const reactiveSend = (event: TEvent | TEvent['type']): void => {\n originalSend(event);\n // Update reactive state after transition\n reactiveState = machine.state;\n reactiveContext = machine.context;\n };\n\n // Return reactive wrapper\n return {\n get state(): TState {\n return reactiveState;\n },\n get context(): TContext {\n return reactiveContext;\n },\n matches(state: TState): boolean {\n return reactiveState === state;\n },\n matchesAny(...states: TState[]): boolean {\n return states.includes(reactiveState);\n },\n can(eventType: TEvent['type']): boolean {\n return machine.can(eventType);\n },\n send: reactiveSend,\n destroy: machine.destroy.bind(machine),\n };\n}\n\n/**\n * Create a machine from an existing config with reactive state\n *\n * Use this when you have a pre-defined machine config that you want\n * to instantiate as a reactive machine in a component.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * import { fromMachine } from 'svoose/svelte';\n * import { toggleConfig } from './machines/toggle';\n *\n * const toggle = fromMachine(toggleConfig);\n * </script>\n * ```\n */\nexport const fromMachine = useMachine;\n\n// Re-export useful types\nexport type { MachineConfig, EventObject } from '../machine/index.js';\n"],
|
|
5
|
+
"mappings": "AAQA,OAAS,iBAAAA,MAA2D,sBAqD7D,SAASC,EAIdC,EAA4F,CAE5F,MAAMC,EAAUH,EAAcE,CAAM,EAGpC,IAAIE,EAAgB,OAAeD,EAAQ,KAAK,EAC5CE,EAAkB,OAAiBF,EAAQ,OAAO,EAGtD,MAAMG,EAAeH,EAAQ,KAAK,KAAKA,CAAO,EAU9C,MAAO,CACL,IAAI,OAAgB,CAClB,OAAOC,CACT,EACA,IAAI,SAAoB,CACtB,OAAOC,CACT,EACA,QAAQE,EAAwB,CAC9B,OAAOH,IAAkBG,CAC3B,EACA,cAAcC,EAA2B,CACvC,OAAOA,EAAO,SAASJ,CAAa,CACtC,EACA,IAAIK,EAAoC,CACtC,OAAON,EAAQ,IAAIM,CAAS,CAC9B,EACA,KAxBoBC,GAAyC,CAC7DJ,EAAaI,CAAK,EAElBN,EAAgBD,EAAQ,MACxBE,EAAkBF,EAAQ,OAC5B,EAoBE,QAASA,EAAQ,QAAQ,KAAKA,CAAO,CACvC,CACF,CAkBO,MAAMQ,EAAcV",
|
|
6
|
+
"names": ["createMachine", "useMachine", "config", "machine", "reactiveState", "reactiveContext", "originalSend", "state", "states", "eventType", "event", "fromMachine"]
|
|
7
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Fetch-based transport with sendBeacon fallback
|
|
3
3
|
*/
|
|
4
|
-
import type { Transport, TransportOptions } from '
|
|
4
|
+
import type { Transport, TransportOptions } from '../types/index.js';
|
|
5
5
|
/**
|
|
6
6
|
* Create a fetch-based transport
|
|
7
7
|
* Uses sendBeacon for page unload, fetch otherwise
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/transport/fetch.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/transport/fetch.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErE;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,SAAS,CAwCX;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,SAAS,CAYpF"}
|
package/dist/transport/fetch.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function a(o,n={}){return{async send(e){if(e.length!==0)try{const
|
|
1
|
+
function a(o,n={}){return{async send(e){if(e.length!==0)try{const t=JSON.stringify(e);if(typeof document<"u"&&document.visibilityState==="hidden"&&typeof navigator<"u"&&navigator.sendBeacon){const r=new Blob([t],{type:"application/json"});if(!navigator.sendBeacon(o,r))throw new Error("sendBeacon failed");return}await fetch(o,{method:"POST",headers:{"Content-Type":"application/json",...n.headers},body:t,keepalive:!0})}catch(t){n.onError?.(t)}}}}function i(o={}){return{async send(n){for(const e of n)o.pretty?console.log("[svoose]",JSON.stringify(e,null,2)):console.log("[svoose]",e)}}}export{i as createConsoleTransport,a as createFetchTransport};
|
|
2
2
|
//# sourceMappingURL=fetch.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/transport/fetch.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Fetch-based transport with sendBeacon fallback\n */\n\nimport type { Transport, TransportOptions } from '
|
|
4
|
+
"sourcesContent": ["/**\n * Fetch-based transport with sendBeacon fallback\n */\n\nimport type { Transport, TransportOptions } from '../types/index.js';\n\n/**\n * Create a fetch-based transport\n * Uses sendBeacon for page unload, fetch otherwise\n *\n * @param endpoint - URL to send events to\n * @param options - Transport options (headers, error callback)\n */\nexport function createFetchTransport(\n endpoint: string,\n options: TransportOptions = {}\n): Transport {\n return {\n async send(events) {\n if (events.length === 0) return;\n\n try {\n const payload = JSON.stringify(events);\n\n // Use sendBeacon when page is hidden (e.g., user navigating away)\n // sendBeacon is more reliable for unload scenarios\n if (\n typeof document !== 'undefined' &&\n document.visibilityState === 'hidden' &&\n typeof navigator !== 'undefined' &&\n navigator.sendBeacon\n ) {\n const blob = new Blob([payload], { type: 'application/json' });\n const success = navigator.sendBeacon(endpoint, blob);\n if (!success) {\n throw new Error('sendBeacon failed');\n }\n return;\n }\n\n // Use fetch for normal operation\n await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n body: payload,\n // keepalive ensures request completes even if page is closed\n keepalive: true,\n });\n } catch (error) {\n options.onError?.(error as Error);\n }\n },\n };\n}\n\n/**\n * Create a console transport for development/debugging\n */\nexport function createConsoleTransport(options: { pretty?: boolean } = {}): Transport {\n return {\n async send(events) {\n for (const event of events) {\n if (options.pretty) {\n console.log('[svoose]', JSON.stringify(event, null, 2));\n } else {\n console.log('[svoose]', event);\n }\n }\n },\n };\n}\n"],
|
|
5
5
|
"mappings": "AAaO,SAASA,EACdC,EACAC,EAA4B,CAAC,EAClB,CACX,MAAO,CACL,MAAM,KAAKC,EAAQ,CACjB,GAAIA,EAAO,SAAW,EAEtB,GAAI,CACF,MAAMC,EAAU,KAAK,UAAUD,CAAM,EAIrC,GACE,OAAO,SAAa,KACpB,SAAS,kBAAoB,UAC7B,OAAO,UAAc,KACrB,UAAU,WACV,CACA,MAAME,EAAO,IAAI,KAAK,CAACD,CAAO,EAAG,CAAE,KAAM,kBAAmB,CAAC,EAE7D,GAAI,CADY,UAAU,WAAWH,EAAUI,CAAI,EAEjD,MAAM,IAAI,MAAM,mBAAmB,EAErC,MACF,CAGA,MAAM,MAAMJ,EAAU,CACpB,OAAQ,OACR,QAAS,CACP,eAAgB,mBAChB,GAAGC,EAAQ,OACb,EACA,KAAME,EAEN,UAAW,EACb,CAAC,CACH,OAASE,EAAO,CACdJ,EAAQ,UAAUI,CAAc,CAClC,CACF,CACF,CACF,CAKO,SAASC,EAAuBL,EAAgC,CAAC,EAAc,CACpF,MAAO,CACL,MAAM,KAAKC,EAAQ,CACjB,UAAWK,KAASL,EACdD,EAAQ,OACV,QAAQ,IAAI,WAAY,KAAK,UAAUM,EAAO,KAAM,CAAC,CAAC,EAEtD,QAAQ,IAAI,WAAYA,CAAK,CAGnC,CACF,CACF",
|
|
6
6
|
"names": ["createFetchTransport", "endpoint", "options", "events", "payload", "blob", "error", "createConsoleTransport", "event"]
|
|
7
7
|
}
|
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Transport interface -
|
|
2
|
+
* Transport interface - re-exported from types for convenience
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
export interface Transport {
|
|
6
|
-
/** Send events to backend. Can return Promise or void for sync transports. */
|
|
7
|
-
send(events: ObserveEvent[]): Promise<void> | void;
|
|
8
|
-
}
|
|
9
|
-
export interface TransportOptions {
|
|
10
|
-
headers?: Record<string, string>;
|
|
11
|
-
onError?: (error: Error) => void;
|
|
12
|
-
}
|
|
4
|
+
export type { Transport, TransportOptions } from '../types/index.js';
|
|
13
5
|
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -50,7 +50,14 @@ export interface TransitionEvent {
|
|
|
50
50
|
sessionId?: string;
|
|
51
51
|
context?: Record<string, unknown>;
|
|
52
52
|
}
|
|
53
|
-
export
|
|
53
|
+
export interface CustomMetricEvent {
|
|
54
|
+
type: 'custom';
|
|
55
|
+
name: string;
|
|
56
|
+
data: Record<string, unknown>;
|
|
57
|
+
timestamp: number;
|
|
58
|
+
sessionId?: string;
|
|
59
|
+
}
|
|
60
|
+
export type ObserveEvent = VitalEvent | ObserveErrorEvent | TransitionEvent | CustomMetricEvent;
|
|
54
61
|
export interface Transport {
|
|
55
62
|
/** Send events to backend. Can return Promise or void for sync transports. */
|
|
56
63
|
send(events: ObserveEvent[]): Promise<void> | void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;AAExE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,mBAAmB,GAAG,MAAM,CAAC;AAEjE,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,qBAAqB,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,uBAAuB,CAAC;AAMrE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAMD,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,iBAAiB,GAAG,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svoose",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Observability + State Machines for Svelte 5 — the goose that sees everything",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -55,6 +55,11 @@
|
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"svelte": "^5.0.0"
|
|
57
57
|
},
|
|
58
|
+
"peerDependenciesMeta": {
|
|
59
|
+
"svelte": {
|
|
60
|
+
"optional": true
|
|
61
|
+
}
|
|
62
|
+
},
|
|
58
63
|
"devDependencies": {
|
|
59
64
|
"@vitest/coverage-v8": "^2.1.9",
|
|
60
65
|
"esbuild": "^0.27.2",
|