@toyz/loom-analytics 0.1.0
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 +131 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/testing.d.ts +37 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +51 -0
- package/dist/testing.js.map +1 -0
- package/dist/track.d.ts +19 -0
- package/dist/track.d.ts.map +1 -0
- package/dist/track.js +80 -0
- package/dist/track.js.map +1 -0
- package/dist/transport.d.ts +26 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +19 -0
- package/dist/transport.js.map +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# @toyz/loom-analytics
|
|
2
|
+
|
|
3
|
+
Zero-dependency, transport-swappable analytics for [Loom](https://github.com/Toyz/loom). Decorator-driven event tracking.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
npm install @toyz/loom-analytics
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
**One dependency:** `@toyz/loom`. That's it.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### 1. Register a Transport
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { app } from "@toyz/loom";
|
|
19
|
+
import { AnalyticsTransport } from "@toyz/loom-analytics";
|
|
20
|
+
|
|
21
|
+
class PostHogTransport extends AnalyticsTransport {
|
|
22
|
+
track(event: string, meta?: Record<string, any>): void {
|
|
23
|
+
posthog.capture(event, meta);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
app.use(AnalyticsTransport, new PostHogTransport());
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 2. Track Events
|
|
31
|
+
|
|
32
|
+
One decorator, three targets:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { track } from "@toyz/loom-analytics";
|
|
36
|
+
|
|
37
|
+
// Track page views — fires on mount
|
|
38
|
+
@track("page.dashboard", { section: "main" })
|
|
39
|
+
class Dashboard extends LoomElement {
|
|
40
|
+
// Track actions — fires after method call
|
|
41
|
+
@track("button.save")
|
|
42
|
+
handleSave() {
|
|
43
|
+
// ...
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Track state changes — fires on set
|
|
47
|
+
@track("theme.change")
|
|
48
|
+
accessor theme = "dark";
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## API
|
|
55
|
+
|
|
56
|
+
### `@track(event, meta?)`
|
|
57
|
+
|
|
58
|
+
Multi-kind decorator for event tracking. Works on classes, methods, and accessors.
|
|
59
|
+
|
|
60
|
+
| Target | When it fires | Auto metadata |
|
|
61
|
+
| -------- | ----------------------- | ----------------------------- |
|
|
62
|
+
| Class | `connectedCallback` | `{ element: "tag-name" }` |
|
|
63
|
+
| Method | After method invocation | `{ method: "name", args }` |
|
|
64
|
+
| Accessor | On set | `{ property: "name", value }` |
|
|
65
|
+
|
|
66
|
+
### `AnalyticsTransport`
|
|
67
|
+
|
|
68
|
+
Abstract class — implement to send events to any backend.
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
abstract class AnalyticsTransport {
|
|
72
|
+
abstract track(event: string, meta?: Record<string, any>): void;
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Custom Transports
|
|
79
|
+
|
|
80
|
+
Swap backends with one DI line:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
// Google Analytics
|
|
84
|
+
class GATransport extends AnalyticsTransport {
|
|
85
|
+
track(event: string, meta?: Record<string, any>): void {
|
|
86
|
+
gtag("event", event, meta);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Console (dev mode)
|
|
91
|
+
class ConsoleTransport extends AnalyticsTransport {
|
|
92
|
+
track(event: string, meta?: Record<string, any>): void {
|
|
93
|
+
console.log(`[analytics] ${event}`, meta);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
app.use(AnalyticsTransport, new GATransport());
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Every `@track` in the app uses the registered transport. No component changes.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Testing
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import { MockAnalytics } from "@toyz/loom-analytics/testing";
|
|
108
|
+
|
|
109
|
+
const analytics = new MockAnalytics();
|
|
110
|
+
app.use(AnalyticsTransport, analytics);
|
|
111
|
+
|
|
112
|
+
// ... interact with component ...
|
|
113
|
+
|
|
114
|
+
// Assertions
|
|
115
|
+
analytics.assertTracked("button.save");
|
|
116
|
+
analytics.assertTracked("theme.change", { value: "light" });
|
|
117
|
+
analytics.assertNotTracked("page.error");
|
|
118
|
+
|
|
119
|
+
// Inspect history
|
|
120
|
+
console.log(analytics.events);
|
|
121
|
+
// [{ event: "button.save", meta: { ... }, timestamp: ... }]
|
|
122
|
+
|
|
123
|
+
// Reset between tests
|
|
124
|
+
analytics.reset();
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## License
|
|
130
|
+
|
|
131
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomAnalytics — Barrel exports
|
|
3
|
+
*
|
|
4
|
+
* Zero-dependency, transport-swappable analytics for Loom.
|
|
5
|
+
* Decorator-driven event tracking with TC39 Stage 3 decorators.
|
|
6
|
+
*/
|
|
7
|
+
export { track } from "./track";
|
|
8
|
+
export { AnalyticsTransport } from "./transport";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomAnalytics — Barrel exports
|
|
3
|
+
*
|
|
4
|
+
* Zero-dependency, transport-swappable analytics for Loom.
|
|
5
|
+
* Decorator-driven event tracking with TC39 Stage 3 decorators.
|
|
6
|
+
*/
|
|
7
|
+
// Decorator
|
|
8
|
+
export { track } from "./track";
|
|
9
|
+
// Transport
|
|
10
|
+
export { AnalyticsTransport } from "./transport";
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY;AACZ,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,YAAY;AACZ,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomAnalytics — MockAnalytics (testing transport)
|
|
3
|
+
*
|
|
4
|
+
* Records all tracked events for assertions in tests.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* const analytics = new MockAnalytics();
|
|
8
|
+
* app.use(AnalyticsTransport, analytics);
|
|
9
|
+
*
|
|
10
|
+
* // ... interact with component ...
|
|
11
|
+
*
|
|
12
|
+
* analytics.assertTracked("button.click");
|
|
13
|
+
* analytics.assertNotTracked("page.error");
|
|
14
|
+
* console.log(analytics.events);
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
import { AnalyticsTransport } from "./transport";
|
|
18
|
+
export interface TrackedEvent {
|
|
19
|
+
event: string;
|
|
20
|
+
meta?: Record<string, any>;
|
|
21
|
+
timestamp: number;
|
|
22
|
+
}
|
|
23
|
+
export declare class MockAnalytics extends AnalyticsTransport {
|
|
24
|
+
/** All tracked events, in order */
|
|
25
|
+
readonly events: TrackedEvent[];
|
|
26
|
+
/** Track an event — records to the events array */
|
|
27
|
+
track(event: string, meta?: Record<string, any>): void;
|
|
28
|
+
/** Assert that an event was tracked, optionally matching metadata */
|
|
29
|
+
assertTracked(event: string, meta?: Record<string, any>): void;
|
|
30
|
+
/** Assert that an event was NOT tracked */
|
|
31
|
+
assertNotTracked(event: string): void;
|
|
32
|
+
/** Clear all recorded events */
|
|
33
|
+
reset(): void;
|
|
34
|
+
/** Partial metadata match */
|
|
35
|
+
private metaMatches;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=testing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,aAAc,SAAQ,kBAAkB;IACnD,mCAAmC;IACnC,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,CAAM;IAErC,mDAAmD;IACnD,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAItD,qEAAqE;IACrE,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAY9D,2CAA2C;IAC3C,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IASrC,gCAAgC;IAChC,KAAK,IAAI,IAAI;IAIb,6BAA6B;IAC7B,OAAO,CAAC,WAAW;CASpB"}
|
package/dist/testing.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomAnalytics — MockAnalytics (testing transport)
|
|
3
|
+
*
|
|
4
|
+
* Records all tracked events for assertions in tests.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* const analytics = new MockAnalytics();
|
|
8
|
+
* app.use(AnalyticsTransport, analytics);
|
|
9
|
+
*
|
|
10
|
+
* // ... interact with component ...
|
|
11
|
+
*
|
|
12
|
+
* analytics.assertTracked("button.click");
|
|
13
|
+
* analytics.assertNotTracked("page.error");
|
|
14
|
+
* console.log(analytics.events);
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
import { AnalyticsTransport } from "./transport";
|
|
18
|
+
export class MockAnalytics extends AnalyticsTransport {
|
|
19
|
+
/** All tracked events, in order */
|
|
20
|
+
events = [];
|
|
21
|
+
/** Track an event — records to the events array */
|
|
22
|
+
track(event, meta) {
|
|
23
|
+
this.events.push({ event, meta, timestamp: Date.now() });
|
|
24
|
+
}
|
|
25
|
+
/** Assert that an event was tracked, optionally matching metadata */
|
|
26
|
+
assertTracked(event, meta) {
|
|
27
|
+
const match = this.events.find((e) => e.event === event && (!meta || this.metaMatches(e.meta, meta)));
|
|
28
|
+
if (!match) {
|
|
29
|
+
const recorded = this.events.map((e) => e.event).join(", ") || "(none)";
|
|
30
|
+
throw new Error(`[MockAnalytics] Expected "${event}" to be tracked. Recorded: ${recorded}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Assert that an event was NOT tracked */
|
|
34
|
+
assertNotTracked(event) {
|
|
35
|
+
const match = this.events.find((e) => e.event === event);
|
|
36
|
+
if (match) {
|
|
37
|
+
throw new Error(`[MockAnalytics] Expected "${event}" to NOT be tracked, but it was.`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Clear all recorded events */
|
|
41
|
+
reset() {
|
|
42
|
+
this.events.length = 0;
|
|
43
|
+
}
|
|
44
|
+
/** Partial metadata match */
|
|
45
|
+
metaMatches(actual, expected) {
|
|
46
|
+
if (!actual)
|
|
47
|
+
return false;
|
|
48
|
+
return Object.entries(expected).every(([key, value]) => actual[key] === value);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=testing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAQjD,MAAM,OAAO,aAAc,SAAQ,kBAAkB;IACnD,mCAAmC;IAC1B,MAAM,GAAmB,EAAE,CAAC;IAErC,mDAAmD;IACnD,KAAK,CAAC,KAAa,EAAE,IAA0B;QAC7C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,qEAAqE;IACrE,aAAa,CAAC,KAAa,EAAE,IAA0B;QACrD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAC5B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CACtE,CAAC;QACF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC;YACxE,MAAM,IAAI,KAAK,CACb,6BAA6B,KAAK,8BAA8B,QAAQ,EAAE,CAC3E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,2CAA2C;IAC3C,gBAAgB,CAAC,KAAa;QAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;QACzD,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CACb,6BAA6B,KAAK,kCAAkC,CACrE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,KAAK;QACH,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,6BAA6B;IACrB,WAAW,CACjB,MAAuC,EACvC,QAA6B;QAE7B,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAC1B,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,CACnC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,KAAK,CACxC,CAAC;IACJ,CAAC;CACF"}
|
package/dist/track.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomAnalytics — @track decorator
|
|
3
|
+
*
|
|
4
|
+
* Raw TC39 Stage 3 decorator for event tracking.
|
|
5
|
+
* Dispatches on `context.kind` to support class, method, and accessor targets.
|
|
6
|
+
*
|
|
7
|
+
* - **method**: wraps the method — fires track() after each invocation
|
|
8
|
+
* - **accessor**: wraps the setter — fires track() on every set
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* @track("user.save")
|
|
12
|
+
* handleSave() { ... }
|
|
13
|
+
*
|
|
14
|
+
* @track("theme.change")
|
|
15
|
+
* accessor theme = "dark";
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function track(event: string, meta?: Record<string, any>): (value: any, context: DecoratorContext) => any;
|
|
19
|
+
//# sourceMappingURL=track.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track.d.ts","sourceRoot":"","sources":["../src/track.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IACrD,OAAO,GAAG,EAAE,SAAS,gBAAgB,KAAG,GAAG,CA2DpD"}
|
package/dist/track.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomAnalytics — @track decorator
|
|
3
|
+
*
|
|
4
|
+
* Raw TC39 Stage 3 decorator for event tracking.
|
|
5
|
+
* Dispatches on `context.kind` to support class, method, and accessor targets.
|
|
6
|
+
*
|
|
7
|
+
* - **method**: wraps the method — fires track() after each invocation
|
|
8
|
+
* - **accessor**: wraps the setter — fires track() on every set
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* @track("user.save")
|
|
12
|
+
* handleSave() { ... }
|
|
13
|
+
*
|
|
14
|
+
* @track("theme.change")
|
|
15
|
+
* accessor theme = "dark";
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
import { app } from "@toyz/loom";
|
|
19
|
+
import { AnalyticsTransport } from "./transport";
|
|
20
|
+
export function track(event, meta) {
|
|
21
|
+
return (value, context) => {
|
|
22
|
+
switch (context.kind) {
|
|
23
|
+
case "class": {
|
|
24
|
+
// Class decorator: stamp an addInitializer that fires on connect
|
|
25
|
+
// Since we can't hook connectedCallback from here, we stamp a marker
|
|
26
|
+
// and let the test/runtime check for it. For simplicity, we fire
|
|
27
|
+
// track at class-definition time for class-level usage (page views).
|
|
28
|
+
// Actually — we can use addInitializer for per-instance setup, but
|
|
29
|
+
// it doesn't have `this` for class decorators in esbuild.
|
|
30
|
+
// Pragmatic solution: wrap the constructor via a returned subclass.
|
|
31
|
+
// BUT esbuild drops class decorator return values.
|
|
32
|
+
// Final approach: directly wrap connectedCallback on the prototype.
|
|
33
|
+
const ctor = value;
|
|
34
|
+
const originalConnected = ctor.prototype.connectedCallback;
|
|
35
|
+
ctor.prototype.connectedCallback = function () {
|
|
36
|
+
if (originalConnected)
|
|
37
|
+
originalConnected.call(this);
|
|
38
|
+
app.get(AnalyticsTransport).track(event, {
|
|
39
|
+
...meta,
|
|
40
|
+
element: this.tagName.toLowerCase(),
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
case "method": {
|
|
46
|
+
// Method decorator: wrap to fire after invocation
|
|
47
|
+
const method = value;
|
|
48
|
+
const key = String(context.name);
|
|
49
|
+
context.addInitializer(function () {
|
|
50
|
+
const original = method;
|
|
51
|
+
this[key] = function (...args) {
|
|
52
|
+
const result = original.apply(this, args);
|
|
53
|
+
app.get(AnalyticsTransport).track(event, { ...meta, method: key, args });
|
|
54
|
+
return result;
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
case "accessor": {
|
|
60
|
+
// Accessor decorator: wrap the setter to fire on set
|
|
61
|
+
const target = value;
|
|
62
|
+
const key = String(context.name);
|
|
63
|
+
return {
|
|
64
|
+
get() {
|
|
65
|
+
return target.get.call(this);
|
|
66
|
+
},
|
|
67
|
+
set(v) {
|
|
68
|
+
target.set.call(this, v);
|
|
69
|
+
app.get(AnalyticsTransport).track(event, {
|
|
70
|
+
...meta,
|
|
71
|
+
property: key,
|
|
72
|
+
value: v,
|
|
73
|
+
});
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=track.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track.js","sourceRoot":"","sources":["../src/track.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,UAAU,KAAK,CAAC,KAAa,EAAE,IAA0B;IAC7D,OAAO,CAAC,KAAU,EAAE,OAAyB,EAAO,EAAE;QACpD,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,iEAAiE;gBACjE,qEAAqE;gBACrE,kEAAkE;gBAClE,qEAAqE;gBACrE,mEAAmE;gBACnE,0DAA0D;gBAC1D,oEAAoE;gBACpE,mDAAmD;gBACnD,oEAAoE;gBACpE,MAAM,IAAI,GAAG,KAAiB,CAAC;gBAC/B,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC;gBAC3D,IAAI,CAAC,SAAS,CAAC,iBAAiB,GAAG;oBACjC,IAAI,iBAAiB;wBAAE,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACpD,GAAG,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE;wBACvC,GAAG,IAAI;wBACP,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE;qBACpC,CAAC,CAAC;gBACL,CAAC,CAAC;gBACF,MAAM;YACR,CAAC;YAED,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,kDAAkD;gBAClD,MAAM,MAAM,GAAG,KAAiB,CAAC;gBACjC,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACjC,OAAO,CAAC,cAAc,CAAC;oBACrB,MAAM,QAAQ,GAAG,MAAM,CAAC;oBACvB,IAAY,CAAC,GAAG,CAAC,GAAG,UAAU,GAAG,IAAW;wBAC3C,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;wBAC1C,GAAG,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;wBACzE,OAAO,MAAM,CAAC;oBAChB,CAAC,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,MAAM;YACR,CAAC;YAED,KAAK,UAAU,CAAC,CAAC,CAAC;gBAChB,qDAAqD;gBACrD,MAAM,MAAM,GAAG,KAA+C,CAAC;gBAC/D,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACjC,OAAO;oBACL,GAAG;wBACD,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAC/B,CAAC;oBACD,GAAG,CAAY,CAAM;wBACnB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;wBACzB,GAAG,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE;4BACvC,GAAG,IAAI;4BACP,QAAQ,EAAE,GAAG;4BACb,KAAK,EAAE,CAAC;yBACT,CAAC,CAAC;oBACL,CAAC;iBACF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomAnalytics — AnalyticsTransport
|
|
3
|
+
*
|
|
4
|
+
* Abstract base class for analytics transports.
|
|
5
|
+
* Implement this to send events to any analytics backend.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* class PostHogTransport extends AnalyticsTransport {
|
|
9
|
+
* track(event: string, meta?: Record<string, any>): void {
|
|
10
|
+
* posthog.capture(event, meta);
|
|
11
|
+
* }
|
|
12
|
+
* }
|
|
13
|
+
*
|
|
14
|
+
* app.use(AnalyticsTransport, new PostHogTransport());
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare abstract class AnalyticsTransport {
|
|
18
|
+
/**
|
|
19
|
+
* Track an event with optional metadata.
|
|
20
|
+
*
|
|
21
|
+
* @param event - The event name (e.g. "button.click", "page.view")
|
|
22
|
+
* @param meta - Optional metadata payload
|
|
23
|
+
*/
|
|
24
|
+
abstract track(event: string, meta?: Record<string, any>): void;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,8BAAsB,kBAAkB;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;CAChE"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LoomAnalytics — AnalyticsTransport
|
|
3
|
+
*
|
|
4
|
+
* Abstract base class for analytics transports.
|
|
5
|
+
* Implement this to send events to any analytics backend.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* class PostHogTransport extends AnalyticsTransport {
|
|
9
|
+
* track(event: string, meta?: Record<string, any>): void {
|
|
10
|
+
* posthog.capture(event, meta);
|
|
11
|
+
* }
|
|
12
|
+
* }
|
|
13
|
+
*
|
|
14
|
+
* app.use(AnalyticsTransport, new PostHogTransport());
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export class AnalyticsTransport {
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,OAAgB,kBAAkB;CAQvC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@toyz/loom-analytics",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Zero-dependency, transport-swappable analytics for Loom — decorator-driven event tracking",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "toyz",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/Toyz/loom.git",
|
|
11
|
+
"directory": "loom-analytics"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"module": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"import": "./dist/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./testing": {
|
|
26
|
+
"types": "./dist/testing.d.ts",
|
|
27
|
+
"import": "./dist/testing.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc",
|
|
32
|
+
"dev": "tsc --watch",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"clean": "rm -rf dist",
|
|
35
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@toyz/loom": "^0.12.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"happy-dom": "^17.4.4",
|
|
42
|
+
"typescript": "^5.7.0",
|
|
43
|
+
"vitest": "^3.0.0"
|
|
44
|
+
},
|
|
45
|
+
"keywords": [
|
|
46
|
+
"loom",
|
|
47
|
+
"analytics",
|
|
48
|
+
"decorators",
|
|
49
|
+
"tracking",
|
|
50
|
+
"web-components"
|
|
51
|
+
]
|
|
52
|
+
}
|