@fluxtrace/node 3.9.0 → 3.10.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.
Files changed (2) hide show
  1. package/README.md +138 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,138 @@
1
+ # @fluxtrace/node
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@fluxtrace/node)](https://www.npmjs.com/package/@fluxtrace/node)
4
+
5
+ Server-side tracking, identification, and feature flags for FluxTrace.
6
+ Requires Node.js 20 or later. ESM only.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm install @fluxtrace/node
12
+ ```
13
+
14
+ - Package: <https://www.npmjs.com/package/@fluxtrace/node>
15
+ - Zero runtime dependencies. TypeScript types included.
16
+
17
+ ## Usage
18
+
19
+ ```ts
20
+ import { FluxtraceClient } from "@fluxtrace/node";
21
+
22
+ const client = new FluxtraceClient({
23
+ trackingId: "YOUR_TRACKING_ID",
24
+ endpoint: "https://collector.example.com/api/collect",
25
+ });
26
+
27
+ await client.identify("user-123", { plan: "pro" });
28
+ await client.track("checkout_completed", { amount: 4999 });
29
+
30
+ if (await client.isFeatureEnabled("new-checkout")) {
31
+ // ...
32
+ }
33
+ ```
34
+
35
+ ## API
36
+
37
+ ### `new FluxtraceClient(options)`
38
+
39
+ | Option | Required | Default | Description |
40
+ | ------------ | -------- | -------------- | -------------------------------------------------------- |
41
+ | `trackingId` | yes | — | Project tracking id sent as `projectId` on collect |
42
+ | `endpoint` | no | `/api/collect` | Absolute collect URL (the relative default can't be called from Node — always set this server-side) |
43
+ | `apiHost` | no | — | Web origin for flag lookups. When set, flags use `subjectId`; when unset they stay on the collector origin with the deprecated `userId` alias |
44
+ | `fetch` | no | global `fetch` | Override for tests |
45
+
46
+ ### `track(name, props?)`
47
+
48
+ ```ts
49
+ await client.track("checkout_completed", {
50
+ amount: 4999,
51
+ currency: "USD",
52
+ coupon: null, // null/undefined values are allowed
53
+ });
54
+ ```
55
+
56
+ Throws when `name` is missing. Payloads are validated against the
57
+ FluxTrace collect schema client-side before sending.
58
+
59
+ ### `identify(userId, traits?)`
60
+
61
+ ```ts
62
+ await client.identify("user-123", { plan: "pro", role: "admin" });
63
+ ```
64
+
65
+ Sends an identify call and remembers `userId` on the instance, so later
66
+ `track` calls are attributed to that user.
67
+
68
+ ### `getFlags(userId?)`
69
+
70
+ ```ts
71
+ // Flags for the identified user…
72
+ const mine = await client.getFlags();
73
+ // …or for someone else
74
+ const theirs = await client.getFlags("user-456");
75
+ ```
76
+
77
+ Returns the evaluated flag map (`Record<string, boolean>`). Throws
78
+ `CollectError` on HTTP failure. Flag fetching never blocks `track`.
79
+
80
+ ### `isFeatureEnabled(key, userId?)`
81
+
82
+ ```ts
83
+ if (await client.isFeatureEnabled("new-checkout", "user-456")) {
84
+ // serve the new experience
85
+ }
86
+ ```
87
+
88
+ Returns `true` only when the flag is explicitly `true`.
89
+
90
+ ## Reliability
91
+
92
+ - Up to 3 delivery attempts per call with linear backoff.
93
+ - HTTP `429` responses are retried; other non-2xx responses throw
94
+ `CollectError` with the response `status`.
95
+ - Network failures are retried; anything else is thrown immediately.
96
+
97
+ ## Errors
98
+
99
+ ```ts
100
+ import { CollectError, FluxtraceClient } from "@fluxtrace/node";
101
+
102
+ try {
103
+ await client.track("purchase", { amount: 100 });
104
+ } catch (err) {
105
+ if (err instanceof CollectError && err.status === 429) {
106
+ // rate limited — already retried 3× inside the client
107
+ }
108
+ throw err;
109
+ }
110
+ ```
111
+
112
+ `CollectError extends Error` carries a numeric `status` (`400` for invalid
113
+ payloads, the HTTP status otherwise).
114
+
115
+ ## Testing
116
+
117
+ Inject a stub `fetch` — no network needed:
118
+
119
+ ```ts
120
+ const calls: unknown[] = [];
121
+ const client = new FluxtraceClient({
122
+ trackingId: "test-project",
123
+ endpoint: "https://collector.test/api/collect",
124
+ fetch: (async (url: unknown, init?: { body?: string }) => {
125
+ calls.push(JSON.parse(init!.body!));
126
+ return new Response(null, { status: 204 });
127
+ }) as typeof fetch,
128
+ });
129
+
130
+ await client.track("signup");
131
+ console.log(calls.length); // 1
132
+ ```
133
+
134
+ ## Changelog
135
+
136
+ ### 3.9.0
137
+
138
+ - Initial public release.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluxtrace/node",
3
- "version": "3.9.0",
3
+ "version": "3.10.0",
4
4
  "private": false,
5
5
  "description": "Server-side track, identify, and feature flags for FluxTrace",
6
6
  "type": "module",