trashlytics 0.0.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 +319 -0
- package/dist/config.d.ts +101 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/event.d.ts +36 -0
- package/dist/event.d.ts.map +1 -0
- package/dist/index.cjs +463 -0
- package/dist/index.d.cts +50 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +447 -0
- package/dist/internal/id.d.ts +5 -0
- package/dist/internal/id.d.ts.map +1 -0
- package/dist/logger.d.ts +83 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/middleware.d.ts +112 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/tracker.d.ts +49 -0
- package/dist/tracker.d.ts.map +1 -0
- package/dist/transport.d.ts +49 -0
- package/dist/transport.d.ts.map +1 -0
- package/package.json +55 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
let effect = require("effect");
|
|
2
|
+
|
|
3
|
+
//#region src/logger.ts
|
|
4
|
+
/**
|
|
5
|
+
* A logger that outputs to the console.
|
|
6
|
+
* This is the default logger.
|
|
7
|
+
*/
|
|
8
|
+
const consoleLogger = {
|
|
9
|
+
debug: (message, ...args) => {
|
|
10
|
+
if (typeof console !== "undefined" && console.debug) console.debug(`[trashlytics] ${message}`, ...args);
|
|
11
|
+
},
|
|
12
|
+
info: (message, ...args) => {
|
|
13
|
+
if (typeof console !== "undefined" && console.info) console.info(`[trashlytics] ${message}`, ...args);
|
|
14
|
+
},
|
|
15
|
+
warn: (message, ...args) => {
|
|
16
|
+
if (typeof console !== "undefined" && console.warn) console.warn(`[trashlytics] ${message}`, ...args);
|
|
17
|
+
},
|
|
18
|
+
error: (message, ...args) => {
|
|
19
|
+
if (typeof console !== "undefined" && console.error) console.error(`[trashlytics] ${message}`, ...args);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* A logger that does nothing.
|
|
24
|
+
* Use this to silence all library logging.
|
|
25
|
+
*/
|
|
26
|
+
const noopLogger = {
|
|
27
|
+
debug: () => {},
|
|
28
|
+
info: () => {},
|
|
29
|
+
warn: () => {},
|
|
30
|
+
error: () => {}
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Create a logger that only logs messages at or above the specified level.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* import { createMinLevelLogger } from "trashlytics"
|
|
38
|
+
*
|
|
39
|
+
* // Only log warnings and errors
|
|
40
|
+
* const logger = createMinLevelLogger("warn")
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
const createMinLevelLogger = (minLevel) => {
|
|
44
|
+
const levels = {
|
|
45
|
+
debug: 0,
|
|
46
|
+
info: 1,
|
|
47
|
+
warn: 2,
|
|
48
|
+
error: 3
|
|
49
|
+
};
|
|
50
|
+
const minOrdinal = levels[minLevel];
|
|
51
|
+
const shouldLog = (level) => levels[level] >= minOrdinal;
|
|
52
|
+
return {
|
|
53
|
+
debug: (message, ...args) => {
|
|
54
|
+
if (shouldLog("debug")) consoleLogger.debug(message, ...args);
|
|
55
|
+
},
|
|
56
|
+
info: (message, ...args) => {
|
|
57
|
+
if (shouldLog("info")) consoleLogger.info(message, ...args);
|
|
58
|
+
},
|
|
59
|
+
warn: (message, ...args) => {
|
|
60
|
+
if (shouldLog("warn")) consoleLogger.warn(message, ...args);
|
|
61
|
+
},
|
|
62
|
+
error: (message, ...args) => {
|
|
63
|
+
if (shouldLog("error")) consoleLogger.error(message, ...args);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/config.ts
|
|
70
|
+
/**
|
|
71
|
+
* Default configuration values.
|
|
72
|
+
*/
|
|
73
|
+
const defaults = {
|
|
74
|
+
batchSize: 10,
|
|
75
|
+
flushIntervalMs: 5e3,
|
|
76
|
+
queueCapacity: 1e3,
|
|
77
|
+
queueStrategy: "dropping",
|
|
78
|
+
retryAttempts: 3,
|
|
79
|
+
retryDelayMs: 1e3,
|
|
80
|
+
shutdownTimeoutMs: 3e4
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Resolves a partial config with defaults.
|
|
84
|
+
*/
|
|
85
|
+
const resolveConfig = (config) => {
|
|
86
|
+
return {
|
|
87
|
+
batchSize: config.batchSize ?? defaults.batchSize,
|
|
88
|
+
flushIntervalMs: config.flushIntervalMs ?? defaults.flushIntervalMs,
|
|
89
|
+
queueCapacity: config.queueCapacity ?? defaults.queueCapacity,
|
|
90
|
+
queueStrategy: config.queueStrategy ?? defaults.queueStrategy,
|
|
91
|
+
retryAttempts: config.retryAttempts ?? defaults.retryAttempts,
|
|
92
|
+
retryDelayMs: config.retryDelayMs ?? defaults.retryDelayMs,
|
|
93
|
+
shutdownTimeoutMs: config.shutdownTimeoutMs ?? defaults.shutdownTimeoutMs,
|
|
94
|
+
transports: config.transports,
|
|
95
|
+
generateId: config.generateId,
|
|
96
|
+
metadata: config.metadata,
|
|
97
|
+
onError: config.onError,
|
|
98
|
+
logger: config.logger ?? consoleLogger
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region src/event.ts
|
|
104
|
+
/**
|
|
105
|
+
* Creates a new event with the given name, payload, and options.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* const event = createEvent("page_view", { page: "/home" }, {
|
|
110
|
+
* id: "abc123",
|
|
111
|
+
* metadata: { userId: "user_1" }
|
|
112
|
+
* })
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
const createEvent = (name, payload, options) => ({
|
|
116
|
+
id: options.id,
|
|
117
|
+
name,
|
|
118
|
+
timestamp: options.timestamp ?? Date.now(),
|
|
119
|
+
payload,
|
|
120
|
+
metadata: options.metadata ?? {}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region src/middleware.ts
|
|
125
|
+
/**
|
|
126
|
+
* Identity middleware - passes events through unchanged.
|
|
127
|
+
*/
|
|
128
|
+
const identity = (event) => event;
|
|
129
|
+
/**
|
|
130
|
+
* Compose multiple middlewares into one.
|
|
131
|
+
* Middlewares are applied left to right.
|
|
132
|
+
* If any middleware returns null, the event is filtered out.
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```ts
|
|
136
|
+
* const middleware = compose(
|
|
137
|
+
* addMetadata({ appVersion: "1.0.0" }),
|
|
138
|
+
* filter((e) => e.name !== "internal"),
|
|
139
|
+
* )
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
const compose = (...middlewares) => {
|
|
143
|
+
if (middlewares.length === 0) return identity;
|
|
144
|
+
return (event) => {
|
|
145
|
+
let current = event;
|
|
146
|
+
for (const mw of middlewares) {
|
|
147
|
+
if (current === null) return null;
|
|
148
|
+
current = mw(current);
|
|
149
|
+
}
|
|
150
|
+
return current;
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* Filter events based on a predicate.
|
|
155
|
+
* Events that don't match the predicate are dropped.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```ts
|
|
159
|
+
* // Only track production events
|
|
160
|
+
* const prodOnly = filter(() => process.env.NODE_ENV === "production")
|
|
161
|
+
*
|
|
162
|
+
* // Skip internal events
|
|
163
|
+
* const skipInternal = filter((e) => !e.name.startsWith("_"))
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
const filter = (predicate) => {
|
|
167
|
+
return (event) => predicate(event) ? event : null;
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* Add static metadata to events.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```ts
|
|
174
|
+
* const addVersion = addMetadata({
|
|
175
|
+
* appVersion: "1.0.0",
|
|
176
|
+
* environment: "production",
|
|
177
|
+
* })
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
const addMetadata = (metadata) => {
|
|
181
|
+
return (event) => ({
|
|
182
|
+
...event,
|
|
183
|
+
metadata: {
|
|
184
|
+
...event.metadata,
|
|
185
|
+
...metadata
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
};
|
|
189
|
+
/**
|
|
190
|
+
* Add metadata dynamically based on the event.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```ts
|
|
194
|
+
* const addTimezone = addMetadataFrom(() => ({
|
|
195
|
+
* timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
196
|
+
* }))
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
const addMetadataFrom = (fn) => {
|
|
200
|
+
return (event) => ({
|
|
201
|
+
...event,
|
|
202
|
+
metadata: {
|
|
203
|
+
...event.metadata,
|
|
204
|
+
...fn(event)
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
};
|
|
208
|
+
/**
|
|
209
|
+
* Transform the event name.
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```ts
|
|
213
|
+
* // Prefix all event names
|
|
214
|
+
* const prefixed = mapName((name) => `app.${name}`)
|
|
215
|
+
* ```
|
|
216
|
+
*/
|
|
217
|
+
const mapName = (fn) => {
|
|
218
|
+
return (event) => ({
|
|
219
|
+
...event,
|
|
220
|
+
name: fn(event.name)
|
|
221
|
+
});
|
|
222
|
+
};
|
|
223
|
+
/**
|
|
224
|
+
* Transform the event payload.
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```ts
|
|
228
|
+
* // Redact sensitive fields
|
|
229
|
+
* const redact = mapPayload((payload) => ({
|
|
230
|
+
* ...payload,
|
|
231
|
+
* password: "[REDACTED]",
|
|
232
|
+
* }))
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
const mapPayload = (fn) => {
|
|
236
|
+
return (event) => ({
|
|
237
|
+
...event,
|
|
238
|
+
payload: fn(event.payload)
|
|
239
|
+
});
|
|
240
|
+
};
|
|
241
|
+
/**
|
|
242
|
+
* Transform the entire event.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* const transform = map((event) => ({
|
|
247
|
+
* ...event,
|
|
248
|
+
* timestamp: Date.now(),
|
|
249
|
+
* }))
|
|
250
|
+
* ```
|
|
251
|
+
*/
|
|
252
|
+
const map = (fn) => {
|
|
253
|
+
return (event) => fn(event);
|
|
254
|
+
};
|
|
255
|
+
/**
|
|
256
|
+
* Tap into the event stream for side effects.
|
|
257
|
+
* Does not modify the event.
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```ts
|
|
261
|
+
* const logger = tap((event) => console.log("Tracking:", event.name))
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
const tap = (fn) => {
|
|
265
|
+
return (event) => {
|
|
266
|
+
fn(event);
|
|
267
|
+
return event;
|
|
268
|
+
};
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
//#endregion
|
|
272
|
+
//#region src/internal/id.ts
|
|
273
|
+
/**
|
|
274
|
+
* Default ID generator.
|
|
275
|
+
*/
|
|
276
|
+
const generateId = () => {
|
|
277
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) return crypto.randomUUID();
|
|
278
|
+
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
279
|
+
let result = "";
|
|
280
|
+
for (let i = 0; i < 21; i++) result += chars[Math.floor(Math.random() * 36)];
|
|
281
|
+
return result;
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
//#endregion
|
|
285
|
+
//#region src/transport.ts
|
|
286
|
+
/**
|
|
287
|
+
* Error thrown when a transport fails to send events.
|
|
288
|
+
*/
|
|
289
|
+
var TransportError = class extends Error {
|
|
290
|
+
name = "TransportError";
|
|
291
|
+
transport;
|
|
292
|
+
retryable;
|
|
293
|
+
constructor(options) {
|
|
294
|
+
super(options.reason);
|
|
295
|
+
this.transport = options.transport;
|
|
296
|
+
this.retryable = options.retryable;
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
//#endregion
|
|
301
|
+
//#region src/tracker.ts
|
|
302
|
+
/**
|
|
303
|
+
* Tracker - main entry point with vanilla JS API.
|
|
304
|
+
* Uses Effect internally for batching, retry, and queue management.
|
|
305
|
+
*
|
|
306
|
+
* @since 1.0.0
|
|
307
|
+
*/
|
|
308
|
+
/**
|
|
309
|
+
* Create a new tracker instance.
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```ts
|
|
313
|
+
* const tracker = createTracker({
|
|
314
|
+
* transports: [httpTransport],
|
|
315
|
+
* batchSize: 10,
|
|
316
|
+
* flushIntervalMs: 5000,
|
|
317
|
+
* })
|
|
318
|
+
*
|
|
319
|
+
* tracker.track("page_view", { page: "/home" })
|
|
320
|
+
*
|
|
321
|
+
* // Later...
|
|
322
|
+
* await tracker.shutdown()
|
|
323
|
+
* ```
|
|
324
|
+
*/
|
|
325
|
+
const createTracker = (config, middleware) => {
|
|
326
|
+
const resolved = resolveConfig(config);
|
|
327
|
+
const mw = middleware ?? identity;
|
|
328
|
+
const generateId$1 = config.generateId ?? generateId;
|
|
329
|
+
const globalMetadata = config.metadata ?? {};
|
|
330
|
+
let runtime = null;
|
|
331
|
+
let isShutdown = false;
|
|
332
|
+
const ensureRuntime = () => {
|
|
333
|
+
if (isShutdown) throw new Error("Tracker has been shut down");
|
|
334
|
+
if (!runtime) runtime = createRuntime(resolved, mw, generateId$1, globalMetadata);
|
|
335
|
+
return runtime;
|
|
336
|
+
};
|
|
337
|
+
return {
|
|
338
|
+
track: (name, payload) => {
|
|
339
|
+
const rt = ensureRuntime();
|
|
340
|
+
const transformed = mw(createEvent(name, payload, {
|
|
341
|
+
id: generateId$1(),
|
|
342
|
+
metadata: { ...globalMetadata }
|
|
343
|
+
}));
|
|
344
|
+
if (transformed) rt.offer(transformed);
|
|
345
|
+
},
|
|
346
|
+
trackAsync: async (name, payload) => {
|
|
347
|
+
const rt = ensureRuntime();
|
|
348
|
+
const transformed = mw(createEvent(name, payload, {
|
|
349
|
+
id: generateId$1(),
|
|
350
|
+
metadata: { ...globalMetadata }
|
|
351
|
+
}));
|
|
352
|
+
if (transformed) await rt.offerAsync(transformed);
|
|
353
|
+
},
|
|
354
|
+
trackWith: (name, payload, metadata) => {
|
|
355
|
+
const rt = ensureRuntime();
|
|
356
|
+
const transformed = mw(createEvent(name, payload, {
|
|
357
|
+
id: generateId$1(),
|
|
358
|
+
metadata: {
|
|
359
|
+
...globalMetadata,
|
|
360
|
+
...metadata
|
|
361
|
+
}
|
|
362
|
+
}));
|
|
363
|
+
if (transformed) rt.offer(transformed);
|
|
364
|
+
},
|
|
365
|
+
flush: async () => {
|
|
366
|
+
if (!runtime || isShutdown) return;
|
|
367
|
+
await runtime.flush();
|
|
368
|
+
},
|
|
369
|
+
shutdown: async () => {
|
|
370
|
+
if (isShutdown) return;
|
|
371
|
+
isShutdown = true;
|
|
372
|
+
if (runtime) {
|
|
373
|
+
await runtime.shutdown();
|
|
374
|
+
runtime = null;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
};
|
|
379
|
+
const createRuntime = (config, _middleware, _generateId, _globalMetadata) => {
|
|
380
|
+
const queueEffect = createQueue(config.queueCapacity, config.queueStrategy);
|
|
381
|
+
const scope = effect.Effect.runSync(effect.Scope.make());
|
|
382
|
+
const queue = effect.Effect.runSync(queueEffect);
|
|
383
|
+
const retrySchedule = effect.Schedule.exponential(effect.Duration.millis(config.retryDelayMs)).pipe(effect.Schedule.jittered, effect.Schedule.compose(effect.Schedule.recurs(config.retryAttempts)));
|
|
384
|
+
const dispatch = async (events) => {
|
|
385
|
+
if (events.length === 0) return;
|
|
386
|
+
const results = await Promise.allSettled(config.transports.map((transport) => dispatchToTransport(transport, events, retrySchedule)));
|
|
387
|
+
for (const result of results) if (result.status === "rejected") {
|
|
388
|
+
const error = result.reason;
|
|
389
|
+
if (config.onError) config.onError(error, events);
|
|
390
|
+
config.logger.error("Transport failed:", error.message);
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
const batchLoop = effect.Effect.gen(function* () {
|
|
394
|
+
yield* effect.Effect.forever(effect.Effect.gen(function* () {
|
|
395
|
+
const events = yield* effect.Effect.race(effect.Queue.takeBetween(queue, config.batchSize, config.batchSize), effect.Effect.sleep(effect.Duration.millis(config.flushIntervalMs)).pipe(effect.Effect.zipRight(effect.Queue.takeUpTo(queue, config.batchSize))));
|
|
396
|
+
if (events.length > 0) yield* effect.Effect.tryPromise({
|
|
397
|
+
try: () => dispatch([...events]),
|
|
398
|
+
catch: () => /* @__PURE__ */ new Error("Dispatch failed")
|
|
399
|
+
}).pipe(effect.Effect.catchAll(() => effect.Effect.void));
|
|
400
|
+
}));
|
|
401
|
+
});
|
|
402
|
+
const batchFiber = effect.Effect.runFork(batchLoop.pipe(effect.Effect.provideService(effect.Scope.Scope, scope)));
|
|
403
|
+
return {
|
|
404
|
+
offer: (event) => {
|
|
405
|
+
effect.Effect.runFork(effect.Queue.offer(queue, event));
|
|
406
|
+
},
|
|
407
|
+
offerAsync: (event) => effect.Effect.runPromise(effect.Queue.offer(queue, event)).then(() => void 0),
|
|
408
|
+
flush: async () => {
|
|
409
|
+
const events = await effect.Effect.runPromise(effect.Queue.takeAll(queue));
|
|
410
|
+
if (events.length > 0) await dispatch([...events]);
|
|
411
|
+
},
|
|
412
|
+
shutdown: async () => {
|
|
413
|
+
await effect.Effect.runPromise(effect.Fiber.interrupt(batchFiber));
|
|
414
|
+
const events = await effect.Effect.runPromise(effect.Queue.takeAll(queue));
|
|
415
|
+
if (events.length > 0) await dispatch([...events]);
|
|
416
|
+
await effect.Effect.runPromise(effect.Scope.close(scope, effect.Exit.void));
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
};
|
|
420
|
+
const createQueue = (capacity, strategy) => {
|
|
421
|
+
switch (strategy) {
|
|
422
|
+
case "bounded": return effect.Queue.bounded(capacity);
|
|
423
|
+
case "dropping": return effect.Queue.dropping(capacity);
|
|
424
|
+
case "sliding": return effect.Queue.sliding(capacity);
|
|
425
|
+
default: return effect.Queue.dropping(capacity);
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
const dispatchToTransport = async (transport, events, retrySchedule) => {
|
|
429
|
+
const effect$1 = effect.Effect.tryPromise({
|
|
430
|
+
try: () => transport.send(events),
|
|
431
|
+
catch: (error) => {
|
|
432
|
+
if (error instanceof TransportError) return error;
|
|
433
|
+
return new TransportError({
|
|
434
|
+
transport: transport.name,
|
|
435
|
+
reason: String(error),
|
|
436
|
+
retryable: true
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
}).pipe(effect.Effect.retry({
|
|
440
|
+
schedule: retrySchedule,
|
|
441
|
+
while: (err) => err.retryable
|
|
442
|
+
}));
|
|
443
|
+
await effect.Effect.runPromise(effect$1);
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
//#endregion
|
|
447
|
+
exports.TransportError = TransportError;
|
|
448
|
+
exports.addMetadata = addMetadata;
|
|
449
|
+
exports.addMetadataFrom = addMetadataFrom;
|
|
450
|
+
exports.compose = compose;
|
|
451
|
+
exports.consoleLogger = consoleLogger;
|
|
452
|
+
exports.createEvent = createEvent;
|
|
453
|
+
exports.createMinLevelLogger = createMinLevelLogger;
|
|
454
|
+
exports.createTracker = createTracker;
|
|
455
|
+
exports.defaults = defaults;
|
|
456
|
+
exports.filter = filter;
|
|
457
|
+
exports.identity = identity;
|
|
458
|
+
exports.map = map;
|
|
459
|
+
exports.mapName = mapName;
|
|
460
|
+
exports.mapPayload = mapPayload;
|
|
461
|
+
exports.noopLogger = noopLogger;
|
|
462
|
+
exports.resolveConfig = resolveConfig;
|
|
463
|
+
exports.tap = tap;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trashlytics - A lightweight event tracking library.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { createTracker, TransportError } from "trashlytics"
|
|
7
|
+
*
|
|
8
|
+
* const tracker = createTracker({
|
|
9
|
+
* transports: [{
|
|
10
|
+
* name: "http",
|
|
11
|
+
* send: async (events) => {
|
|
12
|
+
* const response = await fetch("/analytics", {
|
|
13
|
+
* method: "POST",
|
|
14
|
+
* body: JSON.stringify(events),
|
|
15
|
+
* })
|
|
16
|
+
* if (!response.ok) {
|
|
17
|
+
* throw new TransportError({
|
|
18
|
+
* transport: "http",
|
|
19
|
+
* reason: `HTTP ${response.status}`,
|
|
20
|
+
* retryable: response.status >= 500,
|
|
21
|
+
* })
|
|
22
|
+
* }
|
|
23
|
+
* },
|
|
24
|
+
* }],
|
|
25
|
+
* batchSize: 10,
|
|
26
|
+
* flushIntervalMs: 5000,
|
|
27
|
+
* })
|
|
28
|
+
*
|
|
29
|
+
* tracker.track("page_view", { page: "/home" })
|
|
30
|
+
* tracker.track("button_click", { buttonId: "signup" })
|
|
31
|
+
*
|
|
32
|
+
* // Graceful shutdown
|
|
33
|
+
* await tracker.shutdown()
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @since 1.0.0
|
|
37
|
+
*/
|
|
38
|
+
export type { QueueStrategy, ResolvedConfig, TrackerConfig } from "./config.js";
|
|
39
|
+
export { defaults, resolveConfig } from "./config.js";
|
|
40
|
+
export type { Event, EventOptions } from "./event.js";
|
|
41
|
+
export { createEvent } from "./event.js";
|
|
42
|
+
export type { Logger, LogLevel } from "./logger.js";
|
|
43
|
+
export { consoleLogger, createMinLevelLogger, noopLogger } from "./logger.js";
|
|
44
|
+
export type { Middleware } from "./middleware.js";
|
|
45
|
+
export { addMetadata, addMetadataFrom, compose, filter, identity, map, mapName, mapPayload, tap, } from "./middleware.js";
|
|
46
|
+
export type { Tracker } from "./tracker.js";
|
|
47
|
+
export { createTracker } from "./tracker.js";
|
|
48
|
+
export type { Transport } from "./transport.js";
|
|
49
|
+
export { TransportError } from "./transport.js";
|
|
50
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trashlytics - A lightweight event tracking library.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { createTracker, TransportError } from "trashlytics"
|
|
7
|
+
*
|
|
8
|
+
* const tracker = createTracker({
|
|
9
|
+
* transports: [{
|
|
10
|
+
* name: "http",
|
|
11
|
+
* send: async (events) => {
|
|
12
|
+
* const response = await fetch("/analytics", {
|
|
13
|
+
* method: "POST",
|
|
14
|
+
* body: JSON.stringify(events),
|
|
15
|
+
* })
|
|
16
|
+
* if (!response.ok) {
|
|
17
|
+
* throw new TransportError({
|
|
18
|
+
* transport: "http",
|
|
19
|
+
* reason: `HTTP ${response.status}`,
|
|
20
|
+
* retryable: response.status >= 500,
|
|
21
|
+
* })
|
|
22
|
+
* }
|
|
23
|
+
* },
|
|
24
|
+
* }],
|
|
25
|
+
* batchSize: 10,
|
|
26
|
+
* flushIntervalMs: 5000,
|
|
27
|
+
* })
|
|
28
|
+
*
|
|
29
|
+
* tracker.track("page_view", { page: "/home" })
|
|
30
|
+
* tracker.track("button_click", { buttonId: "signup" })
|
|
31
|
+
*
|
|
32
|
+
* // Graceful shutdown
|
|
33
|
+
* await tracker.shutdown()
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @since 1.0.0
|
|
37
|
+
*/
|
|
38
|
+
export type { QueueStrategy, ResolvedConfig, TrackerConfig } from "./config.js";
|
|
39
|
+
export { defaults, resolveConfig } from "./config.js";
|
|
40
|
+
export type { Event, EventOptions } from "./event.js";
|
|
41
|
+
export { createEvent } from "./event.js";
|
|
42
|
+
export type { Logger, LogLevel } from "./logger.js";
|
|
43
|
+
export { consoleLogger, createMinLevelLogger, noopLogger } from "./logger.js";
|
|
44
|
+
export type { Middleware } from "./middleware.js";
|
|
45
|
+
export { addMetadata, addMetadataFrom, compose, filter, identity, map, mapName, mapPayload, tap, } from "./middleware.js";
|
|
46
|
+
export type { Tracker } from "./tracker.js";
|
|
47
|
+
export { createTracker } from "./tracker.js";
|
|
48
|
+
export type { Transport } from "./transport.js";
|
|
49
|
+
export { TransportError } from "./transport.js";
|
|
50
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAGH,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEtD,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9E,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EACL,WAAW,EACX,eAAe,EACf,OAAO,EACP,MAAM,EACN,QAAQ,EACR,GAAG,EACH,OAAO,EACP,UAAU,EACV,GAAG,GACJ,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG7C,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
|