Typescript client for Driftline analytics

Add comprehensive JSDoc documentation

+136 -17
+8
CHANGELOG.md
··· 1 1 # Changelog 2 2 3 + ## [0.1.2] - 2025-11-28 4 + 5 + ### Added 6 + 7 + - Full JSDoc documentation for all exports 8 + - Module-level documentation with examples 9 + - Examples for all public methods 10 + 3 11 ## [0.1.1] - 2025-11-28 4 12 5 13 ### Fixed
+1 -1
deno.json
··· 1 1 { 2 2 "name": "@tijs/driftline-client", 3 - "version": "0.1.1", 3 + "version": "0.1.2", 4 4 "license": "MIT", 5 5 "exports": "./mod.ts", 6 6 "compilerOptions": {
+127 -16
mod.ts
··· 1 1 /** 2 - * Driftline Analytics Client 2 + * @module 3 3 * 4 - * TypeScript client for tracking analytics events from ATProto app views. 4 + * Driftline Analytics Client - anonymous analytics for ATProto app views. 5 5 * 6 - * Usage: 7 - * const uid = await deriveUidFromDid(user.did, YOUR_APP_SALT); 8 - * const analytics = new AnalyticsClient({ 9 - * appView: "xyz.kipclip.feed", 10 - * env: "prod", 11 - * collectorUrl: "https://driftline.val.run", 12 - * apiKey: YOUR_API_KEY, 13 - * uid, 14 - * }); 6 + * @example Basic usage 7 + * ```ts 8 + * import { AnalyticsClient, deriveUidFromDid } from "@tijs/driftline-client"; 15 9 * 16 - * await analytics.trackAccountCreated(); 17 - * await analytics.trackView("HomeScreen"); 18 - * await analytics.trackAction("checkin_created", "CheckinScreen", { placeType: "cafe" }); 10 + * // Derive anonymous user ID from DID 11 + * const uid = await deriveUidFromDid(user.did, "your-app-secret-salt"); 12 + * 13 + * const analytics = new AnalyticsClient({ 14 + * appView: "kipclip.com", 15 + * env: "prod", 16 + * collectorUrl: "https://driftline.val.run", 17 + * apiKey: "your-api-key", 18 + * uid, 19 + * }); 20 + * 21 + * // Track events 22 + * await analytics.trackAccountCreated(); 23 + * await analytics.trackView("HomeScreen"); 24 + * await analytics.trackAction("checkin_created", "CheckinScreen", { placeType: "cafe" }); 25 + * ``` 19 26 */ 20 27 28 + /** 29 + * Environment type for analytics events. 30 + * Use "dev" for development/testing, "prod" for production. 31 + */ 21 32 export type Environment = "dev" | "prod"; 33 + 34 + /** 35 + * Type of analytics event. 36 + * - `account` - Track account creation (once per user) 37 + * - `view` - Track screen/page impressions 38 + * - `action` - Track user actions (clicks, submissions, etc.) 39 + */ 22 40 export type EventType = "account" | "view" | "action"; 23 41 42 + /** 43 + * Analytics event payload sent to the collector. 44 + */ 24 45 export type AnalyticsEvent = { 46 + /** Event schema version, always 1 */ 25 47 v: 1; 48 + /** App view identifier (e.g., "kipclip.com") */ 26 49 appView: string; 50 + /** Environment: "dev" or "prod" */ 27 51 env: Environment; 52 + /** ISO 8601 timestamp */ 28 53 ts: string; 54 + /** Pseudonymous user ID (12-char hex) */ 29 55 uid: string; 56 + /** Event type */ 30 57 type: EventType; 58 + /** Event name (e.g., "account_created", "screen_impression", "checkin_created") */ 31 59 name: string; 60 + /** Screen/page name (optional) */ 32 61 screen?: string; 62 + /** Additional properties (optional) */ 33 63 props?: Record<string, unknown>; 34 64 }; 35 65 66 + /** 67 + * Configuration for the AnalyticsClient. 68 + * 69 + * @example 70 + * ```ts 71 + * const config: AnalyticsClientConfig = { 72 + * appView: "kipclip.com", 73 + * env: "prod", 74 + * collectorUrl: "https://driftline.val.run", 75 + * apiKey: "your-api-key", 76 + * uid: "a1b2c3d4e5f6", 77 + * }; 78 + * ``` 79 + */ 36 80 export type AnalyticsClientConfig = { 81 + /** App view identifier (e.g., "kipclip.com") */ 37 82 appView: string; 83 + /** Environment: "dev" or "prod" */ 38 84 env: Environment; 85 + /** Driftline collector URL */ 39 86 collectorUrl: string; 87 + /** API key for authentication */ 40 88 apiKey: string; 89 + /** Pseudonymous user ID from {@link deriveUidFromDid} */ 41 90 uid: string; 42 91 }; 43 92 93 + /** 94 + * Client for sending analytics events to Driftline. 95 + * 96 + * @example 97 + * ```ts 98 + * import { AnalyticsClient, deriveUidFromDid } from "@tijs/driftline-client"; 99 + * 100 + * const uid = await deriveUidFromDid(user.did, "your-salt"); 101 + * 102 + * const analytics = new AnalyticsClient({ 103 + * appView: "kipclip.com", 104 + * env: "prod", 105 + * collectorUrl: "https://driftline.val.run", 106 + * apiKey: "your-api-key", 107 + * uid, 108 + * }); 109 + * 110 + * await analytics.trackView("HomeScreen"); 111 + * await analytics.trackAction("button_clicked", "HomeScreen", { buttonId: "submit" }); 112 + * ``` 113 + */ 44 114 export class AnalyticsClient { 115 + /** 116 + * Create a new AnalyticsClient instance. 117 + * 118 + * @param cfg - Client configuration 119 + */ 45 120 constructor(private cfg: AnalyticsClientConfig) {} 46 121 47 122 private createEvent( ··· 98 173 /** 99 174 * Track when an account is first created/registered for this app view. 100 175 * Should only be called once per user. 176 + * 177 + * @param props - Optional additional properties 178 + * 179 + * @example 180 + * ```ts 181 + * await analytics.trackAccountCreated(); 182 + * await analytics.trackAccountCreated({ referrer: "twitter" }); 183 + * ``` 101 184 */ 102 185 async trackAccountCreated(props?: Record<string, unknown>): Promise<void> { 103 186 const event = this.createEvent( ··· 111 194 112 195 /** 113 196 * Track a screen/view impression. 197 + * 198 + * @param screen - Screen or page name 199 + * @param props - Optional additional properties 200 + * 201 + * @example 202 + * ```ts 203 + * await analytics.trackView("HomeScreen"); 204 + * await analytics.trackView("ProfileScreen", { userId: "123" }); 205 + * ``` 114 206 */ 115 207 async trackView( 116 208 screen: string, ··· 122 214 123 215 /** 124 216 * Track a user action. 217 + * 218 + * @param name - Action name (e.g., "checkin_created", "button_clicked") 219 + * @param screen - Optional screen where the action occurred 220 + * @param props - Optional additional properties 221 + * 222 + * @example 223 + * ```ts 224 + * await analytics.trackAction("checkin_created"); 225 + * await analytics.trackAction("checkin_created", "CheckinScreen"); 226 + * await analytics.trackAction("checkin_created", "CheckinScreen", { placeType: "cafe" }); 227 + * ``` 125 228 */ 126 229 async trackAction( 127 230 name: string, ··· 134 237 } 135 238 136 239 /** 137 - * Derive a pseudonymous user ID from a DID. 240 + * Derive a pseudonymous user ID from a DID using SHA-256. 241 + * 138 242 * The same DID + salt will always produce the same uid. 139 - * Different salts (per app view) produce different uids for the same DID. 243 + * Different salts (per app view) produce different uids for the same DID, 244 + * preventing cross-app-view tracking. 140 245 * 141 246 * @param did - The user's DID (e.g., "did:plc:...") 142 247 * @param salt - App-specific salt (keep secret, store in env vars) 143 248 * @returns 12-character hex string 249 + * 250 + * @example 251 + * ```ts 252 + * const uid = await deriveUidFromDid("did:plc:abc123", "my-secret-salt"); 253 + * // Returns something like "a1b2c3d4e5f6" 254 + * ``` 144 255 */ 145 256 export async function deriveUidFromDid( 146 257 did: string,