trashlytics 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -5
- package/dist/index.cjs +17 -3
- package/dist/index.js +17 -3
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -28,8 +28,14 @@ yarn add trashlytics effect
|
|
|
28
28
|
```typescript
|
|
29
29
|
import { createTracker, TransportError } from "trashlytics"
|
|
30
30
|
|
|
31
|
-
// 1.
|
|
32
|
-
|
|
31
|
+
// 1. Define your event types
|
|
32
|
+
type MyEvents = {
|
|
33
|
+
page_view: { page: string; referrer?: string }
|
|
34
|
+
button_click: { buttonId: string }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// 2. Create a typed tracker with your transport
|
|
38
|
+
const tracker = createTracker<MyEvents>({
|
|
33
39
|
transports: [{
|
|
34
40
|
name: "http",
|
|
35
41
|
send: async (events) => {
|
|
@@ -51,18 +57,18 @@ const tracker = createTracker({
|
|
|
51
57
|
flushIntervalMs: 5000,
|
|
52
58
|
})
|
|
53
59
|
|
|
54
|
-
//
|
|
60
|
+
// 3. Track events with full type safety (fire-and-forget)
|
|
55
61
|
tracker.track("page_view", { page: "/home" })
|
|
56
62
|
tracker.track("button_click", { buttonId: "signup" })
|
|
57
63
|
|
|
58
|
-
//
|
|
64
|
+
// 4. Graceful shutdown when done
|
|
59
65
|
await tracker.shutdown()
|
|
60
66
|
```
|
|
61
67
|
|
|
62
68
|
## Configuration
|
|
63
69
|
|
|
64
70
|
```typescript
|
|
65
|
-
import { createTracker } from "trashlytics"
|
|
71
|
+
import { createTracker, consoleLogger, noopLogger } from "trashlytics"
|
|
66
72
|
|
|
67
73
|
const tracker = createTracker({
|
|
68
74
|
// Required: array of transports
|
|
@@ -92,6 +98,9 @@ const tracker = createTracker({
|
|
|
92
98
|
environment: "production",
|
|
93
99
|
},
|
|
94
100
|
|
|
101
|
+
// Logging (default: consoleLogger)
|
|
102
|
+
logger: consoleLogger, // Use noopLogger to silence output
|
|
103
|
+
|
|
95
104
|
// Error Callback (called after all retries exhausted)
|
|
96
105
|
onError: (error, events) => {
|
|
97
106
|
console.error(`Failed to send ${events.length} events:`, error.message)
|
|
@@ -275,6 +284,54 @@ class TransportError extends Error {
|
|
|
275
284
|
}
|
|
276
285
|
```
|
|
277
286
|
|
|
287
|
+
### Logger
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
interface Logger {
|
|
291
|
+
debug: (message: string, ...args: unknown[]) => void
|
|
292
|
+
info: (message: string, ...args: unknown[]) => void
|
|
293
|
+
warn: (message: string, ...args: unknown[]) => void
|
|
294
|
+
error: (message: string, ...args: unknown[]) => void
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Custom Logging
|
|
299
|
+
|
|
300
|
+
Control library logging output:
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
import { createTracker, consoleLogger, noopLogger, createMinLevelLogger } from "trashlytics"
|
|
304
|
+
|
|
305
|
+
// Default: logs to console
|
|
306
|
+
const tracker = createTracker({
|
|
307
|
+
transports,
|
|
308
|
+
logger: consoleLogger,
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
// Silence all logging
|
|
312
|
+
const silentTracker = createTracker({
|
|
313
|
+
transports,
|
|
314
|
+
logger: noopLogger,
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
// Only log warnings and errors
|
|
318
|
+
const warnTracker = createTracker({
|
|
319
|
+
transports,
|
|
320
|
+
logger: createMinLevelLogger("warn"),
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
// Custom logger integration
|
|
324
|
+
const customTracker = createTracker({
|
|
325
|
+
transports,
|
|
326
|
+
logger: {
|
|
327
|
+
debug: (msg, ...args) => myLogger.debug("[analytics]", msg, ...args),
|
|
328
|
+
info: (msg, ...args) => myLogger.info("[analytics]", msg, ...args),
|
|
329
|
+
warn: (msg, ...args) => myLogger.warn("[analytics]", msg, ...args),
|
|
330
|
+
error: (msg, ...args) => myLogger.error("[analytics]", msg, ...args),
|
|
331
|
+
},
|
|
332
|
+
})
|
|
333
|
+
```
|
|
334
|
+
|
|
278
335
|
## Browser Tips
|
|
279
336
|
|
|
280
337
|
### Beacon API Transport
|
package/dist/index.cjs
CHANGED
|
@@ -422,14 +422,15 @@ const createRuntime = (config, _generateId, _globalMetadata) => {
|
|
|
422
422
|
if (events.length === 0) return;
|
|
423
423
|
const results = await Promise.allSettled(config.transports.map((transport) => dispatchToTransport(transport, events, retrySchedule)));
|
|
424
424
|
for (const result of results) if (result.status === "rejected") {
|
|
425
|
-
const error = result.reason;
|
|
425
|
+
const error = extractTransportError(result.reason);
|
|
426
426
|
if (config.onError) config.onError(error, events);
|
|
427
427
|
config.logger.error("Transport failed:", error.message);
|
|
428
428
|
}
|
|
429
429
|
};
|
|
430
430
|
const batchLoop = effect.Effect.gen(function* () {
|
|
431
431
|
yield* effect.Effect.forever(effect.Effect.gen(function* () {
|
|
432
|
-
|
|
432
|
+
yield* effect.Effect.sleep(effect.Duration.millis(config.flushIntervalMs));
|
|
433
|
+
const events = yield* effect.Queue.takeUpTo(queue, config.batchSize);
|
|
433
434
|
if (events.length > 0) yield* effect.Effect.tryPromise({
|
|
434
435
|
try: () => dispatch([...events]),
|
|
435
436
|
catch: () => /* @__PURE__ */ new Error("Dispatch failed")
|
|
@@ -439,7 +440,7 @@ const createRuntime = (config, _generateId, _globalMetadata) => {
|
|
|
439
440
|
const batchFiber = effect.Effect.runFork(batchLoop.pipe(effect.Effect.provideService(effect.Scope.Scope, scope)));
|
|
440
441
|
return {
|
|
441
442
|
offer: (event) => {
|
|
442
|
-
effect.
|
|
443
|
+
effect.Queue.unsafeOffer(queue, event);
|
|
443
444
|
},
|
|
444
445
|
offerAsync: (event) => effect.Effect.runPromise(effect.Queue.offer(queue, event)).then(() => void 0),
|
|
445
446
|
flush: async () => {
|
|
@@ -479,6 +480,19 @@ const dispatchToTransport = async (transport, events, retrySchedule) => {
|
|
|
479
480
|
}));
|
|
480
481
|
await effect.Effect.runPromise(effect$1);
|
|
481
482
|
};
|
|
483
|
+
const FiberFailureCauseSymbol = Symbol.for("effect/Runtime/FiberFailure/Cause");
|
|
484
|
+
const extractTransportError = (reason) => {
|
|
485
|
+
if (reason instanceof TransportError) return reason;
|
|
486
|
+
if (reason && typeof reason === "object") {
|
|
487
|
+
const cause = reason[FiberFailureCauseSymbol];
|
|
488
|
+
if (cause?.error instanceof TransportError) return cause.error;
|
|
489
|
+
}
|
|
490
|
+
return new TransportError({
|
|
491
|
+
transport: "unknown",
|
|
492
|
+
reason: String(reason),
|
|
493
|
+
retryable: false
|
|
494
|
+
});
|
|
495
|
+
};
|
|
482
496
|
|
|
483
497
|
//#endregion
|
|
484
498
|
exports.TransportError = TransportError;
|
package/dist/index.js
CHANGED
|
@@ -422,14 +422,15 @@ const createRuntime = (config, _generateId, _globalMetadata) => {
|
|
|
422
422
|
if (events.length === 0) return;
|
|
423
423
|
const results = await Promise.allSettled(config.transports.map((transport) => dispatchToTransport(transport, events, retrySchedule)));
|
|
424
424
|
for (const result of results) if (result.status === "rejected") {
|
|
425
|
-
const error = result.reason;
|
|
425
|
+
const error = extractTransportError(result.reason);
|
|
426
426
|
if (config.onError) config.onError(error, events);
|
|
427
427
|
config.logger.error("Transport failed:", error.message);
|
|
428
428
|
}
|
|
429
429
|
};
|
|
430
430
|
const batchLoop = Effect.gen(function* () {
|
|
431
431
|
yield* Effect.forever(Effect.gen(function* () {
|
|
432
|
-
|
|
432
|
+
yield* Effect.sleep(Duration.millis(config.flushIntervalMs));
|
|
433
|
+
const events = yield* Queue.takeUpTo(queue, config.batchSize);
|
|
433
434
|
if (events.length > 0) yield* Effect.tryPromise({
|
|
434
435
|
try: () => dispatch([...events]),
|
|
435
436
|
catch: () => /* @__PURE__ */ new Error("Dispatch failed")
|
|
@@ -439,7 +440,7 @@ const createRuntime = (config, _generateId, _globalMetadata) => {
|
|
|
439
440
|
const batchFiber = Effect.runFork(batchLoop.pipe(Effect.provideService(Scope.Scope, scope)));
|
|
440
441
|
return {
|
|
441
442
|
offer: (event) => {
|
|
442
|
-
|
|
443
|
+
Queue.unsafeOffer(queue, event);
|
|
443
444
|
},
|
|
444
445
|
offerAsync: (event) => Effect.runPromise(Queue.offer(queue, event)).then(() => void 0),
|
|
445
446
|
flush: async () => {
|
|
@@ -479,6 +480,19 @@ const dispatchToTransport = async (transport, events, retrySchedule) => {
|
|
|
479
480
|
}));
|
|
480
481
|
await Effect.runPromise(effect);
|
|
481
482
|
};
|
|
483
|
+
const FiberFailureCauseSymbol = Symbol.for("effect/Runtime/FiberFailure/Cause");
|
|
484
|
+
const extractTransportError = (reason) => {
|
|
485
|
+
if (reason instanceof TransportError) return reason;
|
|
486
|
+
if (reason && typeof reason === "object") {
|
|
487
|
+
const cause = reason[FiberFailureCauseSymbol];
|
|
488
|
+
if (cause?.error instanceof TransportError) return cause.error;
|
|
489
|
+
}
|
|
490
|
+
return new TransportError({
|
|
491
|
+
transport: "unknown",
|
|
492
|
+
reason: String(reason),
|
|
493
|
+
retryable: false
|
|
494
|
+
});
|
|
495
|
+
};
|
|
482
496
|
|
|
483
497
|
//#endregion
|
|
484
498
|
export { TransportError, addMetadata, addMetadataFrom, compose, consoleLogger, createEvent, createMinLevelLogger, createTracker, defaults, filter, identity, map, mapName, mapPayload, noopLogger, resolveConfig, tap };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trashlytics",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.1",
|
|
5
5
|
"description": "A lightweight event tracking library",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"@total-typescript/ts-reset": "0.6.1",
|
|
52
52
|
"@types/node": "25.0.3",
|
|
53
53
|
"rolldown": "1.0.0-beta.57",
|
|
54
|
+
"tsx": "4.21.0",
|
|
54
55
|
"typescript": "5.9.3",
|
|
55
56
|
"ultracite": "6.5.0",
|
|
56
57
|
"vitest": "4.0.16"
|