@toglio/js 0.1.0 → 0.1.1

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 +235 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,235 @@
1
+ # @toglio/js
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@toglio/js)](https://www.npmjs.com/package/@toglio/js)
4
+ [![license](https://img.shields.io/npm/l/@toglio/js)](https://github.com/rbragadev/toglio)
5
+
6
+ JavaScript/TypeScript SDK for [Toglio](https://toglio.io) — evaluate feature flags in any JS runtime: browser, Node.js, Deno, or edge functions.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @toglio/js
12
+ # or
13
+ yarn add @toglio/js
14
+ # or
15
+ pnpm add @toglio/js
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ ```typescript
21
+ import { FeatureFlagsClient } from '@toglio/js';
22
+
23
+ const client = new FeatureFlagsClient({
24
+ baseUrl: 'https://api.toglio.io',
25
+ organization: 'my-org',
26
+ project: 'my-project',
27
+ environment: 'production',
28
+ apiKey: process.env.TOGLIO_SDK_TOKEN!,
29
+ });
30
+
31
+ await client.initialize();
32
+
33
+ if (client.isEnabled('checkout.new-flow')) {
34
+ // new checkout
35
+ }
36
+ ```
37
+
38
+ ## How It Works
39
+
40
+ 1. `initialize()` loads the flag cache from `localStorage` (instant), then fetches fresh flags from the server.
41
+ 2. All reads (`isEnabled`, `getString`, etc.) are **synchronous and sub-millisecond** — no `await` needed.
42
+ 3. A background poller refreshes flags every 30 seconds by default.
43
+ 4. If the server is unreachable, the SDK falls back to the local cache, then to the `defaults` you provided. **It never throws to your application.**
44
+
45
+ ## Configuration
46
+
47
+ ```typescript
48
+ const client = new FeatureFlagsClient({
49
+ // Required
50
+ baseUrl: 'https://api.toglio.io', // Your Toglio API URL
51
+ organization: 'my-org', // Organization slug
52
+ project: 'my-project', // Project slug
53
+ environment: 'production', // Environment slug (dev / staging / production)
54
+ apiKey: 'sdk_token_here', // SDK token from Settings → API Keys
55
+
56
+ // Optional
57
+ userId: 'user_123', // End-user ID — required for gradual rollout & targeting
58
+ attributes: { // End-user attributes for targeting rules
59
+ city: 'New York',
60
+ plan: 'pro',
61
+ role: 'admin',
62
+ },
63
+ pollingInterval: 30_000, // Refresh interval in ms (0 = disable polling)
64
+ defaults: { // Fallback values when offline or flag not found
65
+ 'checkout.new-flow': false,
66
+ 'pricing.variant': 'control',
67
+ },
68
+ onChange: (changes) => { // Called after each poll when flags change
69
+ console.log('Flags updated:', changes);
70
+ },
71
+ });
72
+ ```
73
+
74
+ ## API Reference
75
+
76
+ ### `initialize(): Promise<void>`
77
+
78
+ Fetches flags from the server and starts the background poller. Call once at app startup before reading any flags.
79
+
80
+ ```typescript
81
+ await client.initialize();
82
+ ```
83
+
84
+ ### `isEnabled(key, defaultValue?): boolean`
85
+
86
+ Returns `true` if the flag is enabled. Evaluates targeting rules if `userId` is set.
87
+
88
+ ```typescript
89
+ client.isEnabled('dark-mode'); // false if not found
90
+ client.isEnabled('dark-mode', true); // true if not found
91
+ ```
92
+
93
+ ### `getString(key, defaultValue?): string`
94
+
95
+ ```typescript
96
+ client.getString('ui.theme', 'light'); // 'dark' | 'light' | ...
97
+ ```
98
+
99
+ ### `getNumber(key, defaultValue?): number`
100
+
101
+ ```typescript
102
+ client.getNumber('cart.max-items', 10); // 5 | 10 | ...
103
+ ```
104
+
105
+ ### `getVariant(key, defaultValue?): string`
106
+
107
+ Returns the active variant key for a `VARIANT` type flag. Evaluates targeting rules if `userId` is set.
108
+
109
+ ```typescript
110
+ client.getVariant('pricing-page', 'control'); // 'control' | 'variant_a' | 'variant_b'
111
+ ```
112
+
113
+ ### `getVariantPayload(key): unknown`
114
+
115
+ Returns the JSON payload attached to the active variant, or `null`.
116
+
117
+ ```typescript
118
+ const payload = client.getVariantPayload('pricing-page');
119
+ // { cta: 'Start free trial', color: '#4f46e5' }
120
+ ```
121
+
122
+ ### `getAll(): FlagMap`
123
+
124
+ Returns all resolved flags as a plain object.
125
+
126
+ ```typescript
127
+ const flags = client.getAll();
128
+ // { 'dark-mode': true, 'pricing-page': 'variant_a', ... }
129
+ ```
130
+
131
+ ### `getStatus(): ClientStatus`
132
+
133
+ ```typescript
134
+ const { initialized, lastFetchAt, fetchError } = client.getStatus();
135
+ ```
136
+
137
+ ### `addOnChange(callback): () => void`
138
+
139
+ Subscribes to flag changes. Returns an unsubscribe function.
140
+
141
+ ```typescript
142
+ const unsubscribe = client.addOnChange((changes) => {
143
+ changes.forEach(({ key, previous, current }) => {
144
+ console.log(`${key}: ${previous} → ${current}`);
145
+ });
146
+ });
147
+
148
+ // Later:
149
+ unsubscribe();
150
+ ```
151
+
152
+ ### `destroy(): void`
153
+
154
+ Stops the background poller. Call when shutting down the app.
155
+
156
+ ```typescript
157
+ client.destroy();
158
+ ```
159
+
160
+ ## Targeting & Rollout
161
+
162
+ ### Gradual Rollout
163
+
164
+ Set `userId` to enable deterministic rollout. The SDK sends it as `X-Toglio-User-Id` on every request. The server uses `flagKey + userId` to place users in stable buckets.
165
+
166
+ ```typescript
167
+ const client = new FeatureFlagsClient({
168
+ // ...
169
+ userId: currentUser.id, // stable identifier — not related to Toglio admin users
170
+ });
171
+ ```
172
+
173
+ - `rolloutPercentage = 100`: all users get the flag.
174
+ - `rolloutPercentage = 0`: no users get the flag.
175
+ - `1–99`: deterministic bucket per user.
176
+
177
+ ### Targeting Rules
178
+
179
+ Set `attributes` to enable client-side targeting rule evaluation. Rules are created in the Toglio dashboard and shipped in the SDK response.
180
+
181
+ ```typescript
182
+ const client = new FeatureFlagsClient({
183
+ // ...
184
+ userId: currentUser.id,
185
+ attributes: {
186
+ city: currentUser.city, // string
187
+ tags: currentUser.tags, // string[]
188
+ plan: currentUser.plan,
189
+ },
190
+ });
191
+ ```
192
+
193
+ Supported operators: `IN`, `NOT_IN`, `EQUALS`, `NOT_EQUALS`, `CONTAINS`, `MATCHES_REGEX`.
194
+
195
+ ## SSR / Server-Side Usage
196
+
197
+ The SDK uses `localStorage` for caching when available and silently skips it in environments where it is not (Node.js, edge runtimes). Everything else works the same.
198
+
199
+ ```typescript
200
+ // pages/index.tsx (Next.js)
201
+ export async function getServerSideProps() {
202
+ const client = new FeatureFlagsClient({ /* ... */ });
203
+ await client.initialize();
204
+
205
+ return {
206
+ props: {
207
+ showBanner: client.isEnabled('homepage.banner'),
208
+ },
209
+ };
210
+ }
211
+ ```
212
+
213
+ For server-side usage, set `pollingInterval: 0` to disable the poller and call `client.destroy()` after reading flags.
214
+
215
+ ## TypeScript
216
+
217
+ All types are exported:
218
+
219
+ ```typescript
220
+ import type {
221
+ FeatureFlagsClientConfig,
222
+ FlagMap,
223
+ FlagValue,
224
+ FlagChange,
225
+ ClientStatus,
226
+ } from '@toglio/js';
227
+ ```
228
+
229
+ ## React
230
+
231
+ For React projects, use [`@toglio/react`](https://www.npmjs.com/package/@toglio/react) which provides a context Provider and hooks (`useFlag`, `useVariant`, `useFlagsReady`).
232
+
233
+ ## License
234
+
235
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toglio/js",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Toglio — JavaScript/TypeScript SDK",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",