Skip to content

Commit 6a4b0e2

Browse files
committed
chore: add readme
1 parent eb6b3ac commit 6a4b0e2

1 file changed

Lines changed: 179 additions & 0 deletions

File tree

README.md

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
# Formo Node SDK
2+
3+
Server-side Node.js SDK for [Formo Analytics](https://formo.so).
4+
5+
## Installation
6+
7+
```bash
8+
npm install @formo/analytics-node
9+
# or
10+
pnpm add @formo/analytics-node
11+
```
12+
13+
## Quick Start
14+
15+
```typescript
16+
import { FormoAnalytics } from "@formo/analytics-node";
17+
18+
const analytics = new FormoAnalytics("your-write-key");
19+
20+
// Track an event
21+
await analytics.track({
22+
anonymousId: "device-uuid",
23+
event: "Purchase Completed",
24+
properties: {
25+
orderId: "123",
26+
total: 99.99,
27+
currency: "USD",
28+
},
29+
});
30+
31+
// Identify a user
32+
await analytics.identify({
33+
anonymousId: "device-uuid",
34+
userId: "user-123",
35+
traits: {
36+
email: "user@example.com",
37+
plan: "premium",
38+
},
39+
});
40+
41+
// Flush pending events before shutdown
42+
await analytics.flush();
43+
```
44+
45+
## API Reference
46+
47+
### `new FormoAnalytics(writeKey, options?)`
48+
49+
Create a new analytics instance.
50+
51+
| Option | Type | Default | Description |
52+
| --------------- | -------- | -------- | -------------------------------- |
53+
| `flushAt` | `number` | `20` | Flush when N events are queued |
54+
| `flushInterval` | `number` | `30000` | Flush every N milliseconds |
55+
| `maxQueueSize` | `number` | `500000` | Flush when queue exceeds N bytes |
56+
| `retryCount` | `number` | `3` | Retry failed requests N times |
57+
58+
```typescript
59+
const analytics = new FormoAnalytics("your-write-key", {
60+
flushAt: 10,
61+
flushInterval: 10000,
62+
});
63+
```
64+
65+
### `analytics.track(event)`
66+
67+
Track a custom event.
68+
69+
```typescript
70+
await analytics.track({
71+
// Required
72+
anonymousId: "device-uuid", // Device/session identifier
73+
event: "Button Clicked", // Event name
74+
75+
// Optional
76+
userId: "user-123", // Your user identifier
77+
properties: {}, // Event properties
78+
address: "0x...", // Ethereum wallet address
79+
context: {}, // Additional context
80+
});
81+
```
82+
83+
### `analytics.identify(event)`
84+
85+
Identify a user and their traits.
86+
87+
```typescript
88+
await analytics.identify({
89+
// Required
90+
anonymousId: "device-uuid", // Device/session identifier
91+
userId: "user-123", // Your user identifier
92+
93+
// Optional
94+
traits: {}, // User properties
95+
address: "0x...", // Ethereum wallet address
96+
context: {}, // Additional context
97+
});
98+
```
99+
100+
### `analytics.flush()`
101+
102+
Manually flush all pending events.
103+
104+
```typescript
105+
// Call before process exit to ensure all events are sent
106+
await analytics.flush();
107+
```
108+
109+
## Ethereum Address Handling
110+
111+
The SDK automatically validates and checksums Ethereum addresses using EIP-55:
112+
113+
```typescript
114+
await analytics.track({
115+
anonymousId: "device-uuid",
116+
event: "Wallet Connected",
117+
address: "0xab5801a7d398351b8be11c439e05c5b3259aec9b", // lowercase
118+
// Stored as: 0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B (checksummed)
119+
});
120+
```
121+
122+
Invalid addresses will throw a `ValidationError`.
123+
124+
## Error Handling
125+
126+
```typescript
127+
import { FormoAnalytics, ValidationError } from "@formo/analytics-node";
128+
129+
try {
130+
await analytics.track({
131+
anonymousId: "",
132+
event: "Test",
133+
});
134+
} catch (error) {
135+
if (error instanceof ValidationError) {
136+
console.error(`Validation failed: ${error.field} - ${error.reason}`);
137+
}
138+
}
139+
```
140+
141+
## Graceful Shutdown
142+
143+
The SDK automatically registers handlers for `SIGTERM`, `SIGINT`, and `beforeExit` to flush pending events before process termination.
144+
145+
For manual control:
146+
147+
```typescript
148+
process.on("SIGTERM", async () => {
149+
await analytics.flush();
150+
process.exit(0);
151+
});
152+
```
153+
154+
## Development
155+
156+
### Running Tests
157+
158+
```bash
159+
# Unit tests
160+
pnpm test
161+
162+
# Integration tests (requires API key)
163+
FORMO_WRITE_KEY=your-key pnpm run test:integration
164+
```
165+
166+
### Project Structure
167+
168+
```
169+
sdk-node/
170+
├── src/
171+
│ ├── FormoAnalytics.ts # Main SDK class
172+
│ ├── queue/ # Event batching and retry logic
173+
│ ├── types/ # TypeScript type definitions
174+
│ ├── utils/ # Address checksumming, property normalization
175+
│ └── validators/ # Input validation
176+
├── sdks/
177+
│ └── sdk-server-side-typescript/ # Generated API client (Stainless)
178+
└── package.json
179+
```

0 commit comments

Comments
 (0)