@affectively/aeon-pages 1.3.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/CHANGELOG.md +112 -0
- package/README.md +625 -0
- package/examples/basic/aeon.config.ts +39 -0
- package/examples/basic/components/Cursor.tsx +86 -0
- package/examples/basic/components/OfflineIndicator.tsx +103 -0
- package/examples/basic/components/PresenceBar.tsx +77 -0
- package/examples/basic/package.json +20 -0
- package/examples/basic/pages/index.tsx +80 -0
- package/package.json +101 -0
- package/packages/analytics/README.md +309 -0
- package/packages/analytics/build.ts +35 -0
- package/packages/analytics/package.json +50 -0
- package/packages/analytics/src/click-tracker.ts +368 -0
- package/packages/analytics/src/context-bridge.ts +319 -0
- package/packages/analytics/src/data-layer.ts +302 -0
- package/packages/analytics/src/gtm-loader.ts +239 -0
- package/packages/analytics/src/index.ts +230 -0
- package/packages/analytics/src/merkle-tree.ts +489 -0
- package/packages/analytics/src/provider.tsx +300 -0
- package/packages/analytics/src/types.ts +320 -0
- package/packages/analytics/src/use-analytics.ts +296 -0
- package/packages/analytics/tsconfig.json +19 -0
- package/packages/benchmarks/src/benchmark.test.ts +691 -0
- package/packages/cli/dist/index.js +61899 -0
- package/packages/cli/package.json +43 -0
- package/packages/cli/src/commands/build.test.ts +682 -0
- package/packages/cli/src/commands/build.ts +890 -0
- package/packages/cli/src/commands/dev.ts +473 -0
- package/packages/cli/src/commands/init.ts +409 -0
- package/packages/cli/src/commands/start.ts +297 -0
- package/packages/cli/src/index.ts +105 -0
- package/packages/directives/src/use-aeon.ts +272 -0
- package/packages/mcp-server/package.json +51 -0
- package/packages/mcp-server/src/index.ts +178 -0
- package/packages/mcp-server/src/resources.ts +346 -0
- package/packages/mcp-server/src/tools/index.ts +36 -0
- package/packages/mcp-server/src/tools/navigation.ts +545 -0
- package/packages/mcp-server/tsconfig.json +21 -0
- package/packages/react/package.json +40 -0
- package/packages/react/src/Link.tsx +388 -0
- package/packages/react/src/components/InstallPrompt.tsx +286 -0
- package/packages/react/src/components/OfflineDiagnostics.tsx +677 -0
- package/packages/react/src/components/PushNotifications.tsx +453 -0
- package/packages/react/src/hooks/useAeonNavigation.ts +219 -0
- package/packages/react/src/hooks/useConflicts.ts +277 -0
- package/packages/react/src/hooks/useNetworkState.ts +209 -0
- package/packages/react/src/hooks/usePilotNavigation.ts +254 -0
- package/packages/react/src/hooks/useServiceWorker.ts +278 -0
- package/packages/react/src/hooks.ts +195 -0
- package/packages/react/src/index.ts +151 -0
- package/packages/react/src/provider.tsx +467 -0
- package/packages/react/tsconfig.json +19 -0
- package/packages/runtime/README.md +399 -0
- package/packages/runtime/build.ts +48 -0
- package/packages/runtime/package.json +71 -0
- package/packages/runtime/schema.sql +40 -0
- package/packages/runtime/src/api-routes.ts +465 -0
- package/packages/runtime/src/benchmark.ts +171 -0
- package/packages/runtime/src/cache.ts +479 -0
- package/packages/runtime/src/durable-object.ts +1341 -0
- package/packages/runtime/src/index.ts +360 -0
- package/packages/runtime/src/navigation.test.ts +421 -0
- package/packages/runtime/src/navigation.ts +422 -0
- package/packages/runtime/src/nextjs-adapter.ts +272 -0
- package/packages/runtime/src/offline/encrypted-queue.test.ts +607 -0
- package/packages/runtime/src/offline/encrypted-queue.ts +478 -0
- package/packages/runtime/src/offline/encryption.test.ts +412 -0
- package/packages/runtime/src/offline/encryption.ts +397 -0
- package/packages/runtime/src/offline/types.ts +465 -0
- package/packages/runtime/src/predictor.ts +371 -0
- package/packages/runtime/src/registry.ts +351 -0
- package/packages/runtime/src/router/context-extractor.ts +661 -0
- package/packages/runtime/src/router/esi-control-react.tsx +2053 -0
- package/packages/runtime/src/router/esi-control.ts +541 -0
- package/packages/runtime/src/router/esi-cyrano.ts +779 -0
- package/packages/runtime/src/router/esi-format-react.tsx +1744 -0
- package/packages/runtime/src/router/esi-react.tsx +1065 -0
- package/packages/runtime/src/router/esi-translate-observer.ts +476 -0
- package/packages/runtime/src/router/esi-translate-react.tsx +556 -0
- package/packages/runtime/src/router/esi-translate.ts +503 -0
- package/packages/runtime/src/router/esi.ts +666 -0
- package/packages/runtime/src/router/heuristic-adapter.test.ts +295 -0
- package/packages/runtime/src/router/heuristic-adapter.ts +557 -0
- package/packages/runtime/src/router/index.ts +298 -0
- package/packages/runtime/src/router/merkle-capability.ts +473 -0
- package/packages/runtime/src/router/speculation.ts +451 -0
- package/packages/runtime/src/router/types.ts +630 -0
- package/packages/runtime/src/router.test.ts +470 -0
- package/packages/runtime/src/router.ts +302 -0
- package/packages/runtime/src/server.ts +481 -0
- package/packages/runtime/src/service-worker-push.ts +319 -0
- package/packages/runtime/src/service-worker.ts +553 -0
- package/packages/runtime/src/skeleton-hydrate.ts +237 -0
- package/packages/runtime/src/speculation.test.ts +389 -0
- package/packages/runtime/src/speculation.ts +486 -0
- package/packages/runtime/src/storage.test.ts +1297 -0
- package/packages/runtime/src/storage.ts +1048 -0
- package/packages/runtime/src/sync/conflict-resolver.test.ts +528 -0
- package/packages/runtime/src/sync/conflict-resolver.ts +565 -0
- package/packages/runtime/src/sync/coordinator.test.ts +608 -0
- package/packages/runtime/src/sync/coordinator.ts +596 -0
- package/packages/runtime/src/tree-compiler.ts +295 -0
- package/packages/runtime/src/types.ts +728 -0
- package/packages/runtime/src/worker.ts +327 -0
- package/packages/runtime/tsconfig.json +20 -0
- package/packages/runtime/wasm/aeon_pages_runtime.d.ts +504 -0
- package/packages/runtime/wasm/aeon_pages_runtime.js +1657 -0
- package/packages/runtime/wasm/aeon_pages_runtime_bg.wasm +0 -0
- package/packages/runtime/wasm/aeon_pages_runtime_bg.wasm.d.ts +196 -0
- package/packages/runtime/wasm/package.json +21 -0
- package/packages/runtime/wrangler.toml +41 -0
- package/packages/runtime-wasm/Cargo.lock +436 -0
- package/packages/runtime-wasm/Cargo.toml +29 -0
- package/packages/runtime-wasm/pkg/aeon_pages_runtime.d.ts +480 -0
- package/packages/runtime-wasm/pkg/aeon_pages_runtime.js +1568 -0
- package/packages/runtime-wasm/pkg/aeon_pages_runtime_bg.wasm +0 -0
- package/packages/runtime-wasm/pkg/aeon_pages_runtime_bg.wasm.d.ts +192 -0
- package/packages/runtime-wasm/pkg/package.json +21 -0
- package/packages/runtime-wasm/src/hydrate.rs +352 -0
- package/packages/runtime-wasm/src/lib.rs +191 -0
- package/packages/runtime-wasm/src/render.rs +629 -0
- package/packages/runtime-wasm/src/router.rs +298 -0
- package/packages/runtime-wasm/src/skeleton.rs +430 -0
- package/rfcs/RFC-001-ZERO-DEPENDENCY-RENDERING.md +1446 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# @affectively/aeon-pages-analytics
|
|
2
|
+
|
|
3
|
+
**Zero-instrumentation analytics.** Automatic click tracking with Merkle tree node IDs and rich ESI context.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
bun add @affectively/aeon-pages-analytics
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## What is this?
|
|
10
|
+
|
|
11
|
+
Aeon Analytics automatically tracks every click in your application without any manual instrumentation. Each click event includes:
|
|
12
|
+
|
|
13
|
+
- **Merkle hash** of the clicked component (content-addressable, stable across renders)
|
|
14
|
+
- **Full tree path** from root to clicked node
|
|
15
|
+
- **Rich ESI context** (user tier, emotion state, features, session info)
|
|
16
|
+
- **Element metadata** (text, aria-label, role, href)
|
|
17
|
+
- **Position data** (viewport and document coordinates)
|
|
18
|
+
|
|
19
|
+
Everything flows to GTM dataLayer for GA4 custom events.
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### 1. Server-Side: Inject GTM
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
// In your HTML template
|
|
27
|
+
const gtmContainerId = env.GTM_CONTAINER_ID;
|
|
28
|
+
|
|
29
|
+
const html = `
|
|
30
|
+
<!DOCTYPE html>
|
|
31
|
+
<html>
|
|
32
|
+
<head>
|
|
33
|
+
<!-- GTM Script -->
|
|
34
|
+
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
|
35
|
+
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
|
36
|
+
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
|
37
|
+
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
|
38
|
+
})(window,document,'script','dataLayer','${gtmContainerId}');</script>
|
|
39
|
+
</head>
|
|
40
|
+
<body>
|
|
41
|
+
<!-- GTM noscript -->
|
|
42
|
+
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=${gtmContainerId}"
|
|
43
|
+
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
|
|
44
|
+
...
|
|
45
|
+
</body>
|
|
46
|
+
</html>
|
|
47
|
+
`;
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. Client-Side: Initialize Tracking
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import {
|
|
54
|
+
initClickTracker,
|
|
55
|
+
initContextBridgeWithRetry,
|
|
56
|
+
pushPageView,
|
|
57
|
+
syncESIToDataLayer,
|
|
58
|
+
} from '@affectively/aeon-pages-analytics';
|
|
59
|
+
|
|
60
|
+
// Initialize on page load
|
|
61
|
+
initContextBridgeWithRetry({ maxRetries: 3, retryDelayMs: 500 });
|
|
62
|
+
initClickTracker({
|
|
63
|
+
debounceMs: 100,
|
|
64
|
+
maxTextLength: 150,
|
|
65
|
+
excludeSelectors: ['.no-track', '[data-no-track]'],
|
|
66
|
+
includePosition: true,
|
|
67
|
+
});
|
|
68
|
+
pushPageView();
|
|
69
|
+
|
|
70
|
+
// Track SPA navigation
|
|
71
|
+
history.pushState = function(...args) {
|
|
72
|
+
originalPushState(...args);
|
|
73
|
+
syncESIToDataLayer();
|
|
74
|
+
pushPageView();
|
|
75
|
+
};
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 3. React Provider (Optional)
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import { AeonAnalyticsProvider } from '@affectively/aeon-pages-analytics';
|
|
82
|
+
|
|
83
|
+
export default function App({ Component, pageProps }) {
|
|
84
|
+
return (
|
|
85
|
+
<AeonAnalyticsProvider
|
|
86
|
+
gtmContainerId="GTM-XXXXXX"
|
|
87
|
+
trackClicks={true}
|
|
88
|
+
syncESIContext={true}
|
|
89
|
+
>
|
|
90
|
+
<Component {...pageProps} />
|
|
91
|
+
</AeonAnalyticsProvider>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Merkle Tree Hashing
|
|
97
|
+
|
|
98
|
+
Each component gets a deterministic hash based on its content:
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { hashNodeSync, buildMerkleTreeSync } from '@affectively/aeon-pages-analytics';
|
|
102
|
+
|
|
103
|
+
// Hash = SHA-256(type + sorted_props + child_hashes)
|
|
104
|
+
const hash = hashNodeSync('Button', { onClick: fn }, ['child1hash']);
|
|
105
|
+
// Returns: "a1b2c3d4e5f6" (12-char truncated hash)
|
|
106
|
+
|
|
107
|
+
// Build tree from component tree
|
|
108
|
+
const merkleTree = buildMerkleTreeSync(componentTree);
|
|
109
|
+
// Map<nodeId, MerkleNode> with hashes and paths
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Why Merkle Trees?
|
|
113
|
+
|
|
114
|
+
- **Stable IDs** - Same content = same hash, even if DOM order changes
|
|
115
|
+
- **Tree paths** - Full ancestry for every click
|
|
116
|
+
- **Change detection** - Compare trees to find what changed
|
|
117
|
+
- **Cacheable** - Same tree = same hashes
|
|
118
|
+
|
|
119
|
+
## DataLayer Events
|
|
120
|
+
|
|
121
|
+
### Context Event (on page load)
|
|
122
|
+
```javascript
|
|
123
|
+
{
|
|
124
|
+
event: 'aeon.context',
|
|
125
|
+
user: { tier: 'pro', id: 'user_123', sessionId: 'sess_abc' },
|
|
126
|
+
emotion: { primary: 'focused', valence: 0.3, arousal: 0.6 },
|
|
127
|
+
features: { aiInference: true, emotionTracking: true },
|
|
128
|
+
device: { viewport: { width: 1920, height: 1080 }, connection: '4g' },
|
|
129
|
+
time: { localHour: 14, timezone: 'America/New_York' }
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Click Event
|
|
134
|
+
```javascript
|
|
135
|
+
{
|
|
136
|
+
event: 'aeon.click',
|
|
137
|
+
aeon: { version: '0.1.0', timestamp: 1707321600000 },
|
|
138
|
+
click: {
|
|
139
|
+
merkleHash: 'a1b2c3d4e5f6',
|
|
140
|
+
treePath: ['root', 'layout', 'header', 'nav', 'settings-button'],
|
|
141
|
+
treePathHashes: ['f1e2d3c4b5a6', 'b2c3d4e5f6a1', ...],
|
|
142
|
+
element: {
|
|
143
|
+
tagName: 'BUTTON',
|
|
144
|
+
text: 'Settings',
|
|
145
|
+
ariaLabel: 'Open settings menu',
|
|
146
|
+
role: 'button'
|
|
147
|
+
},
|
|
148
|
+
position: { x: 1450, y: 32, viewportX: 1450, viewportY: 32 }
|
|
149
|
+
},
|
|
150
|
+
context: {
|
|
151
|
+
userTier: 'pro',
|
|
152
|
+
emotionState: { primary: 'focused', valence: 0.3, arousal: 0.6 },
|
|
153
|
+
sessionId: 'sess_abc'
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Page View Event
|
|
159
|
+
```javascript
|
|
160
|
+
{
|
|
161
|
+
event: 'aeon.pageview',
|
|
162
|
+
page: {
|
|
163
|
+
path: '/dashboard',
|
|
164
|
+
title: 'Dashboard - AFFECTIVELY',
|
|
165
|
+
merkleRoot: 'abc123def456'
|
|
166
|
+
},
|
|
167
|
+
user: { tier: 'pro', sessionId: 'sess_abc' }
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## API Reference
|
|
172
|
+
|
|
173
|
+
### Click Tracking
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
// Initialize
|
|
177
|
+
initClickTracker(options?: ClickTrackingOptions): void
|
|
178
|
+
|
|
179
|
+
// Stop tracking
|
|
180
|
+
stopClickTracker(): void
|
|
181
|
+
|
|
182
|
+
// Check status
|
|
183
|
+
isClickTrackerActive(): boolean
|
|
184
|
+
|
|
185
|
+
// Manual tracking
|
|
186
|
+
trackClick(element: HTMLElement, event: MouseEvent): void
|
|
187
|
+
trackInteraction(type: string, data: Record<string, unknown>): void
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Context Bridge
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
// ESI state access
|
|
194
|
+
getESIState(): ESIState | null
|
|
195
|
+
hasESIState(): boolean
|
|
196
|
+
getESIProperty<K extends keyof ESIState>(key: K): ESIState[K] | null
|
|
197
|
+
|
|
198
|
+
// Sync to dataLayer
|
|
199
|
+
syncESIToDataLayer(): void
|
|
200
|
+
pushPageView(): void
|
|
201
|
+
|
|
202
|
+
// Watch for changes
|
|
203
|
+
watchESIChanges(): () => void
|
|
204
|
+
initContextBridge(): void
|
|
205
|
+
initContextBridgeWithRetry(options: { maxRetries: number, retryDelayMs: number }): void
|
|
206
|
+
|
|
207
|
+
// Utilities
|
|
208
|
+
isAdmin(): boolean
|
|
209
|
+
hasFeature(feature: string): boolean
|
|
210
|
+
meetsTierRequirement(tier: UserTier): boolean
|
|
211
|
+
getUserTier(): UserTier
|
|
212
|
+
getEmotionState(): EmotionState | null
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Merkle Tree
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
// Sync hashing (uses djb2)
|
|
219
|
+
hashNodeSync(type: string, props: object, childHashes: string[]): string
|
|
220
|
+
buildMerkleTreeSync(tree: ComponentTree): MerkleTree
|
|
221
|
+
|
|
222
|
+
// Async hashing (uses SHA-256)
|
|
223
|
+
hashNodeAsync(type: string, props: object, childHashes: string[]): Promise<string>
|
|
224
|
+
buildMerkleTree(tree: ComponentTree): Promise<MerkleTree>
|
|
225
|
+
|
|
226
|
+
// DOM helpers
|
|
227
|
+
getMerkleAttributes(node: MerkleNode): Record<string, string>
|
|
228
|
+
parseMerkleFromElement(el: HTMLElement): MerkleNode | null
|
|
229
|
+
findNearestMerkleElement(el: HTMLElement): HTMLElement | null
|
|
230
|
+
|
|
231
|
+
// Verification
|
|
232
|
+
verifyMerkleTree(tree: MerkleTree): boolean
|
|
233
|
+
diffMerkleTrees(a: MerkleTree, b: MerkleTree): MerkleDiff
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### GTM Loader
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
// Inject GTM
|
|
240
|
+
injectGTM(config: GTMConfig): void
|
|
241
|
+
injectGTMNoScript(containerId: string): void
|
|
242
|
+
initializeGTM(config: GTMConfig): void
|
|
243
|
+
|
|
244
|
+
// SSR helpers
|
|
245
|
+
generateGTMScriptTag(containerId: string): string
|
|
246
|
+
generateGTMNoScriptTag(containerId: string): string
|
|
247
|
+
generateDataLayerScript(initialData: object): string
|
|
248
|
+
|
|
249
|
+
// Status
|
|
250
|
+
isGTMInjected(): boolean
|
|
251
|
+
isGTMReady(): boolean
|
|
252
|
+
waitForGTM(timeout?: number): Promise<void>
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Configuration
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
interface AnalyticsConfig {
|
|
259
|
+
// Required: GTM container ID
|
|
260
|
+
gtmContainerId: string; // 'GTM-XXXXXX'
|
|
261
|
+
|
|
262
|
+
// Optional: Customize behavior
|
|
263
|
+
trackClicks?: boolean; // Default: true
|
|
264
|
+
trackPageViews?: boolean; // Default: true
|
|
265
|
+
syncESIContext?: boolean; // Default: true
|
|
266
|
+
|
|
267
|
+
// Click tracking options
|
|
268
|
+
clickOptions?: {
|
|
269
|
+
debounceMs?: number; // Default: 0
|
|
270
|
+
maxTextLength?: number; // Default: 100
|
|
271
|
+
excludeSelectors?: string[]; // e.g., ['.no-track']
|
|
272
|
+
includePosition?: boolean; // Default: true
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
// Data layer customization
|
|
276
|
+
dataLayerName?: string; // Default: 'dataLayer'
|
|
277
|
+
eventPrefix?: string; // Default: 'aeon'
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## ESI State Types
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
type UserTier = 'free' | 'starter' | 'pro' | 'enterprise' | 'admin';
|
|
285
|
+
|
|
286
|
+
interface ESIState {
|
|
287
|
+
userTier: UserTier;
|
|
288
|
+
isAdmin?: boolean;
|
|
289
|
+
userId?: string;
|
|
290
|
+
sessionId?: string;
|
|
291
|
+
isNewSession?: boolean;
|
|
292
|
+
emotionState?: {
|
|
293
|
+
primary: string;
|
|
294
|
+
valence: number;
|
|
295
|
+
arousal: number;
|
|
296
|
+
};
|
|
297
|
+
preferences?: Record<string, unknown>;
|
|
298
|
+
features?: Record<string, boolean>;
|
|
299
|
+
recentPages?: string[];
|
|
300
|
+
viewport?: { width: number; height: number };
|
|
301
|
+
connection?: string;
|
|
302
|
+
localHour?: number;
|
|
303
|
+
timezone?: string;
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## License
|
|
308
|
+
|
|
309
|
+
MIT
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build script for @affectively/aeon-pages-analytics
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { build } from 'bun';
|
|
6
|
+
|
|
7
|
+
async function runBuild() {
|
|
8
|
+
console.log('Building @affectively/aeon-pages-analytics...');
|
|
9
|
+
|
|
10
|
+
// Build main entry point
|
|
11
|
+
await build({
|
|
12
|
+
entrypoints: ['./src/index.ts'],
|
|
13
|
+
outdir: './dist',
|
|
14
|
+
format: 'esm',
|
|
15
|
+
target: 'browser',
|
|
16
|
+
minify: false,
|
|
17
|
+
sourcemap: 'external',
|
|
18
|
+
external: ['react'],
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Build provider separately for /react export
|
|
22
|
+
await build({
|
|
23
|
+
entrypoints: ['./src/provider.tsx'],
|
|
24
|
+
outdir: './dist',
|
|
25
|
+
format: 'esm',
|
|
26
|
+
target: 'browser',
|
|
27
|
+
minify: false,
|
|
28
|
+
sourcemap: 'external',
|
|
29
|
+
external: ['react'],
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
console.log('Build complete!');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
runBuild().catch(console.error);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@affectively/aeon-pages-analytics",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Automatic click tracking and GTM integration for @affectively/aeon-pages",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./react": {
|
|
14
|
+
"import": "./dist/provider.js",
|
|
15
|
+
"types": "./dist/provider.d.ts"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "bun run build.ts && tsc --declaration --emitDeclarationOnly",
|
|
20
|
+
"dev": "bun --watch ./src/index.ts",
|
|
21
|
+
"test": "bun test",
|
|
22
|
+
"prepublishOnly": "bun run build"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"react": ">=18.0.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"typescript": "^5.7.0",
|
|
33
|
+
"@types/react": "^19.0.0",
|
|
34
|
+
"react": "^19.0.0"
|
|
35
|
+
},
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/affectively/aeon-pages"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"aeon",
|
|
43
|
+
"pages",
|
|
44
|
+
"analytics",
|
|
45
|
+
"gtm",
|
|
46
|
+
"google-tag-manager",
|
|
47
|
+
"click-tracking",
|
|
48
|
+
"merkle-tree"
|
|
49
|
+
]
|
|
50
|
+
}
|