@nanoflags/sdk 0.0.0-stage → 0.4.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/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +374 -2
- package/dist/index-D5qa8ji-.d.cts +302 -0
- package/dist/index-D5qa8ji-.d.ts +302 -0
- package/dist/index.cjs +12 -0
- package/dist/index.d.cts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +1 -0
- package/dist/node.cjs +108 -0
- package/dist/node.d.cts +35 -0
- package/dist/node.d.ts +35 -0
- package/dist/node.js +101 -0
- package/dist/react.cjs +65 -0
- package/dist/react.d.cts +28 -0
- package/dist/react.d.ts +28 -0
- package/dist/react.js +62 -0
- package/dist/src-CVTvEKbT.js +1556 -0
- package/dist/src-IVd-Wps4.cjs +1615 -0
- package/package.json +98 -3
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
type FlagType = "boolean" | "string" | "number" | "json";
|
|
2
|
+
type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
3
|
+
[k: string]: JsonValue;
|
|
4
|
+
};
|
|
5
|
+
type Operator = "eq" | "neq" | "in" | "not_in" | "contains" | "starts_with" | "ends_with" | "gt" | "gte" | "lt" | "lte" | "exists" | "not_exists" | "segment" | "not_segment";
|
|
6
|
+
interface Condition {
|
|
7
|
+
/** Context attribute name, e.g. "region". Ignored for segment operators. */
|
|
8
|
+
attribute: string;
|
|
9
|
+
op: Operator;
|
|
10
|
+
/** Comparison value. Array for in/not_in; segment key for segment operators. */
|
|
11
|
+
value?: JsonValue;
|
|
12
|
+
}
|
|
13
|
+
type Serve = {
|
|
14
|
+
type: "fixed";
|
|
15
|
+
value: JsonValue;
|
|
16
|
+
} | {
|
|
17
|
+
type: "rollout";
|
|
18
|
+
/** 0–100, up to two decimals. */
|
|
19
|
+
percentage: number;
|
|
20
|
+
/** Value for contexts inside the allocation. */
|
|
21
|
+
value: JsonValue;
|
|
22
|
+
/** Value for matching contexts outside the allocation. */
|
|
23
|
+
otherwise: JsonValue;
|
|
24
|
+
/** Context attribute used for bucketing. Defaults to "key". */
|
|
25
|
+
bucketBy?: string;
|
|
26
|
+
/** Documented seed. Defaults to the flag key, so allocations are independent per flag. */
|
|
27
|
+
seed?: string;
|
|
28
|
+
};
|
|
29
|
+
interface Rule {
|
|
30
|
+
id: string;
|
|
31
|
+
description?: string;
|
|
32
|
+
match: "all" | "any";
|
|
33
|
+
conditions: Condition[];
|
|
34
|
+
serve: Serve;
|
|
35
|
+
}
|
|
36
|
+
interface FlagConfig {
|
|
37
|
+
type: FlagType;
|
|
38
|
+
/** When false the flag short-circuits to `off`. */
|
|
39
|
+
enabled: boolean;
|
|
40
|
+
rules: Rule[];
|
|
41
|
+
/** Served when the flag is enabled and no rule matches. */
|
|
42
|
+
default: JsonValue;
|
|
43
|
+
/** Served when the flag is disabled. */
|
|
44
|
+
off: JsonValue;
|
|
45
|
+
/** Only client-exposed flags are included in bundles served to browser keys. */
|
|
46
|
+
clientExposed?: boolean;
|
|
47
|
+
}
|
|
48
|
+
interface Segment {
|
|
49
|
+
match: "all" | "any";
|
|
50
|
+
conditions: Condition[];
|
|
51
|
+
}
|
|
52
|
+
interface Bundle {
|
|
53
|
+
schema: 1;
|
|
54
|
+
/**
|
|
55
|
+
* Engine version the bundle was produced for (`ENGINE_VERSION` of the publisher). Absent in bundles from before it
|
|
56
|
+
* existed (treated as 1). SDKs refuse a bundle whose `engine` is newer than the engine they ship.
|
|
57
|
+
*/
|
|
58
|
+
engine?: number;
|
|
59
|
+
project: string;
|
|
60
|
+
environment: string;
|
|
61
|
+
/** Published revision number. 0 means "draft / never published". */
|
|
62
|
+
revision: number;
|
|
63
|
+
flags: Record<string, FlagConfig>;
|
|
64
|
+
segments: Record<string, Segment>;
|
|
65
|
+
}
|
|
66
|
+
/** Attributes supplied by the application. `key` is the stable identity used for bucketing. */
|
|
67
|
+
type Context = {
|
|
68
|
+
key?: string;
|
|
69
|
+
} & Record<string, JsonValue | undefined>;
|
|
70
|
+
type Reason = "rule_match" | "default" | "off" | "flag_not_found" | "error";
|
|
71
|
+
interface TraceStep {
|
|
72
|
+
kind: "config" | "rule" | "allocation" | "result";
|
|
73
|
+
title: string;
|
|
74
|
+
detail: string;
|
|
75
|
+
matched?: boolean;
|
|
76
|
+
}
|
|
77
|
+
interface Evaluation<T = JsonValue> {
|
|
78
|
+
flagKey: string;
|
|
79
|
+
value: T;
|
|
80
|
+
reason: Reason;
|
|
81
|
+
/** Zero-based index of the matching rule. */
|
|
82
|
+
ruleIndex?: number;
|
|
83
|
+
ruleId?: string;
|
|
84
|
+
/** For rollout rules: whether the context fell inside the allocation, and its bucket (0–99.99). */
|
|
85
|
+
inRollout?: boolean;
|
|
86
|
+
bucket?: number;
|
|
87
|
+
revision: number;
|
|
88
|
+
trace: TraceStep[];
|
|
89
|
+
error?: string;
|
|
90
|
+
}
|
|
91
|
+
/** Persistence for the last bundle. Values are opaque strings owned by the SDK. */
|
|
92
|
+
interface Store {
|
|
93
|
+
get(): Promise<string | null>;
|
|
94
|
+
set(value: string): Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Bundle signature verification (Ed25519 over a canonical string, WebCrypto only).
|
|
98
|
+
*
|
|
99
|
+
* canonical = "nanoflags-bundle-v1\n<environment_id>\n<revision>\n<checksum>\n<sha256 hex of the bundle JSON text>"
|
|
100
|
+
*
|
|
101
|
+
* Only PUBLIC keys are handled here. Private and admin keys never enter the SDK.
|
|
102
|
+
*/
|
|
103
|
+
interface VerifyOptions {
|
|
104
|
+
/**
|
|
105
|
+
* Public Ed25519 keys as JWK (`{ kty: "OKP", crv: "Ed25519", x, kid? }`), or `"fetch"` to load them
|
|
106
|
+
* once from `GET /v1/keys` on the configured edge (again, at most once a minute, when a bundle names an unknown
|
|
107
|
+
* key id). Pinning keys in your build is stronger than `"fetch"`: fetched keys are only as trustworthy as the
|
|
108
|
+
* connection they arrived over. Omitted: the embedded production keys for `https://edge.nanoflags.io`, `"fetch"`
|
|
109
|
+
* for any other edge.
|
|
110
|
+
*/
|
|
111
|
+
publicKeys?: readonly JsonWebKey[] | "fetch";
|
|
112
|
+
/**
|
|
113
|
+
* Also reject bundles that carry no signature (the edge's unsigned fallback, `X-NanoFlags-Signed: false`): the SDK
|
|
114
|
+
* keeps its bundle and fetches again shortly instead. Default true for `https://edge.nanoflags.io`, false otherwise.
|
|
115
|
+
*/
|
|
116
|
+
require?: boolean;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The hosted NanoFlags edge and the public halves of its bundle-signing keys (Ed25519, safe to embed).
|
|
120
|
+
*
|
|
121
|
+
* With `baseUrl` equal to `OFFICIAL_EDGE_URL` the SDK verifies every bundle against these keys by default
|
|
122
|
+
* (`verify.require` defaults to true there). A bundle signed with a key id that is not listed here — a rotation that
|
|
123
|
+
* happened after this SDK version was built — makes the SDK load `GET /v1/keys` from the edge once and verify against
|
|
124
|
+
* the keys it lists as well. Rotation procedure: RUNTIME.md, "Signing-key rotation".
|
|
125
|
+
*/
|
|
126
|
+
declare const OFFICIAL_EDGE_URL = "https://edge.nanoflags.io";
|
|
127
|
+
declare const OFFICIAL_SIGNING_KEYS: readonly (JsonWebKey & {
|
|
128
|
+
kid: string;
|
|
129
|
+
})[];
|
|
130
|
+
declare const SDK_VERSION = "0.4.0";
|
|
131
|
+
/** Newest bundle format (`bundle.engine`) this SDK can evaluate. Newer bundles are refused; the previous one stays in use. */
|
|
132
|
+
declare const SUPPORTED_ENGINE_VERSION = 1;
|
|
133
|
+
/** WebSocket close code of the edge for an environment that was deleted: the SDK stops reconnecting. */
|
|
134
|
+
declare const CLOSE_ENVIRONMENT_DELETED = 4004;
|
|
135
|
+
/** Header that carries a test-session token between services. */
|
|
136
|
+
declare const SESSION_HEADER = "x-nanoflags-session";
|
|
137
|
+
type ClientStatus = "not-ready" | "ready" | "stale";
|
|
138
|
+
/** How updates currently reach the client: pushed over the live WebSocket, announced over SSE, or polled. */
|
|
139
|
+
type Transport = "live" | "stream" | "poll";
|
|
140
|
+
/** WebSocket subprotocol of `/v1/live`. The key travels as a second protocol entry, never in the URL. */
|
|
141
|
+
declare const LIVE_PROTOCOL = "nanoflags.v1";
|
|
142
|
+
/** The part of the WHATWG WebSocket the SDK uses (browsers, Node ≥ 22, Deno, Bun, the `ws` package). */
|
|
143
|
+
interface WebSocketLike {
|
|
144
|
+
send(data: string): void;
|
|
145
|
+
close(code?: number, reason?: string): void;
|
|
146
|
+
onopen: ((event: any) => any) | null;
|
|
147
|
+
onmessage: ((event: any) => any) | null;
|
|
148
|
+
onclose: ((event: any) => any) | null;
|
|
149
|
+
onerror: ((event: any) => any) | null;
|
|
150
|
+
}
|
|
151
|
+
type WebSocketConstructor = new (url: string, protocols?: string | string[]) => WebSocketLike;
|
|
152
|
+
interface EventsOptions {
|
|
153
|
+
/** Default true. */
|
|
154
|
+
enabled?: boolean;
|
|
155
|
+
/** Fraction of evaluations reported, 0–1. Default 0.1. */
|
|
156
|
+
sampleRate?: number;
|
|
157
|
+
/** Default 10000. How often queued events are sent. */
|
|
158
|
+
flushIntervalMs?: number;
|
|
159
|
+
/**
|
|
160
|
+
* Default 60000. While no events are queued, the service report ("this service runs revision N")
|
|
161
|
+
* goes out at this interval instead of on every flush interval.
|
|
162
|
+
*/
|
|
163
|
+
reportIntervalMs?: number;
|
|
164
|
+
/**
|
|
165
|
+
* Decides what part of the evaluation context leaves the process with a sampled event.
|
|
166
|
+
* Default: no attribute VALUES are sent — only the names of the attributes that the flag's
|
|
167
|
+
* rules reference and that were present, mapped to the value's type (e.g. `{ region: "string" }`).
|
|
168
|
+
*/
|
|
169
|
+
redact?: (ctx: Context) => Record<string, JsonValue | undefined>;
|
|
170
|
+
/** Random source for sampling; injectable for tests. */
|
|
171
|
+
random?: () => number;
|
|
172
|
+
}
|
|
173
|
+
interface ClientOptions {
|
|
174
|
+
/** `nf_srv_…` on servers, `nf_pub_…` in browsers. Never ship a server key to a browser. */
|
|
175
|
+
sdkKey: string;
|
|
176
|
+
/** Base URL of the NanoFlags edge, e.g. `https://flags.example.com`. */
|
|
177
|
+
baseUrl: string;
|
|
178
|
+
/** Name shown in "which revision is this service running". */
|
|
179
|
+
service?: string;
|
|
180
|
+
/** Default 30000. `0` disables polling. */
|
|
181
|
+
pollIntervalMs?: number;
|
|
182
|
+
/**
|
|
183
|
+
* Default true. Receive updates without polling: over the live WebSocket when the runtime has
|
|
184
|
+
* one, otherwise (or when the socket cannot be established) over SSE. `false` disables both.
|
|
185
|
+
*/
|
|
186
|
+
streaming?: boolean;
|
|
187
|
+
/** Default true. `false` skips the live WebSocket and uses SSE + polling as SDK 0.2 did. */
|
|
188
|
+
live?: boolean;
|
|
189
|
+
/** Default 300000. Safety-poll interval while the live socket is healthy (`pollIntervalMs` applies otherwise; `pollIntervalMs: 0` disables both). */
|
|
190
|
+
livePollIntervalMs?: number;
|
|
191
|
+
/** WebSocket implementation. Default: the global `WebSocket` (browsers, Node ≥ 22). Without one the SDK uses SSE + polling. */
|
|
192
|
+
webSocket?: WebSocketConstructor;
|
|
193
|
+
/** A bundle obtained elsewhere (e.g. embedded at build time or passed from the server). */
|
|
194
|
+
bootstrap?: Bundle;
|
|
195
|
+
/** Persistence. Default: IndexedDB in browsers, none elsewhere. `false` disables it. */
|
|
196
|
+
store?: Store | false;
|
|
197
|
+
events?: EventsOptions | false;
|
|
198
|
+
/**
|
|
199
|
+
* Verify bundle signatures before a new bundle replaces the current one. A bundle whose signature
|
|
200
|
+
* does not verify is rejected: the previous bundle stays in use and an `error` (`code: "signature"`)
|
|
201
|
+
* is emitted. Without `require`, bundles the edge marks as unsigned are still accepted.
|
|
202
|
+
*
|
|
203
|
+
* Default: with `baseUrl` = `https://edge.nanoflags.io` the SDK verifies against the embedded production keys
|
|
204
|
+
* (`OFFICIAL_SIGNING_KEYS`, plus `GET /v1/keys` once when a bundle names an unknown key id) with `require: true`;
|
|
205
|
+
* with any other `baseUrl` nothing is verified unless configured. `false` turns verification off explicitly.
|
|
206
|
+
*/
|
|
207
|
+
verify?: VerifyOptions | false;
|
|
208
|
+
fetch?: typeof fetch;
|
|
209
|
+
}
|
|
210
|
+
/** The flag accessors shared by the client and by session-scoped evaluators. */
|
|
211
|
+
interface FlagEvaluator {
|
|
212
|
+
boolean(key: string, fallback: boolean, ctx?: Context): boolean;
|
|
213
|
+
string(key: string, fallback: string, ctx?: Context): string;
|
|
214
|
+
number(key: string, fallback: number, ctx?: Context): number;
|
|
215
|
+
json<T extends JsonValue = JsonValue>(key: string, fallback: T, ctx?: Context): T;
|
|
216
|
+
/** Full engine result (value, reason, matched rule, trace). No type check is applied. */
|
|
217
|
+
evaluate<T extends JsonValue = JsonValue>(key: string, fallback: T, ctx?: Context): Evaluation<T>;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Evaluator bound to one test session. While `active`, flags are evaluated against the session's
|
|
221
|
+
* pinned bundle with the context `{ ...session.context, ...ctx }` and sampled events carry the
|
|
222
|
+
* session id. When the session is unknown, not permitted for this service, or expired, it evaluates
|
|
223
|
+
* exactly like the client (`active` is false). It never throws.
|
|
224
|
+
*/
|
|
225
|
+
interface SessionEvaluator extends FlagEvaluator {
|
|
226
|
+
/** True while the session is known and has not expired. Re-evaluated on every read. */
|
|
227
|
+
readonly active: boolean;
|
|
228
|
+
/** Session id, or null when the session could not be resolved. */
|
|
229
|
+
readonly id: string | null;
|
|
230
|
+
/** ISO timestamp, or null when the session could not be resolved. */
|
|
231
|
+
readonly expiresAt: string | null;
|
|
232
|
+
/** Revision evaluations currently run against (the pinned one while active, otherwise the client's). */
|
|
233
|
+
readonly revision: number | null;
|
|
234
|
+
}
|
|
235
|
+
interface SessionOptions {
|
|
236
|
+
/** Service name sent as `X-NanoFlags-Service`. Defaults to the client's `service`. */
|
|
237
|
+
service?: string;
|
|
238
|
+
}
|
|
239
|
+
interface UpdateEvent {
|
|
240
|
+
revision: number;
|
|
241
|
+
previousRevision: number | null;
|
|
242
|
+
checksum: string | null;
|
|
243
|
+
source: "network" | "store" | "bootstrap";
|
|
244
|
+
/**
|
|
245
|
+
* Milliseconds from the commit of the revision in the database to this event — only for revisions
|
|
246
|
+
* pushed over the live socket (`transport: "live"`) that carry the commit time; otherwise null.
|
|
247
|
+
* It compares the database's clock with this machine's, so it is as accurate as their clocks agree.
|
|
248
|
+
*/
|
|
249
|
+
latencyMs: number | null;
|
|
250
|
+
/** How this bundle arrived: pushed (`live`), fetched after an SSE notification (`stream`), or anything else (`poll`). */
|
|
251
|
+
transport: Transport;
|
|
252
|
+
}
|
|
253
|
+
interface NanoFlagsClient {
|
|
254
|
+
/** Resolves once a usable bundle is loaded, or once the first load attempt has finished without one. Never rejects. */
|
|
255
|
+
ready(): Promise<void>;
|
|
256
|
+
readonly status: ClientStatus;
|
|
257
|
+
/** Revision of the bundle in use, or null when none is loaded. */
|
|
258
|
+
readonly revision: number | null;
|
|
259
|
+
/** How updates reach this client right now: `live` while the WebSocket is open, `stream` while SSE is in use, else `poll`. */
|
|
260
|
+
readonly transport: Transport;
|
|
261
|
+
boolean(key: string, fallback: boolean, ctx?: Context): boolean;
|
|
262
|
+
string(key: string, fallback: string, ctx?: Context): string;
|
|
263
|
+
number(key: string, fallback: number, ctx?: Context): number;
|
|
264
|
+
json<T extends JsonValue = JsonValue>(key: string, fallback: T, ctx?: Context): T;
|
|
265
|
+
/** Full engine result (value, reason, matched rule, trace). No type check is applied. */
|
|
266
|
+
evaluate<T extends JsonValue = JsonValue>(key: string, fallback: T, ctx?: Context): Evaluation<T>;
|
|
267
|
+
/**
|
|
268
|
+
* Resolve a test session (`GET /v1/session`, once per token until it expires) and return an
|
|
269
|
+
* evaluator scoped to it. Never rejects: an unknown or expired session yields an evaluator
|
|
270
|
+
* whose `active` is false and that behaves like the client.
|
|
271
|
+
*/
|
|
272
|
+
session(token: string | null | undefined, options?: SessionOptions): Promise<SessionEvaluator>;
|
|
273
|
+
/**
|
|
274
|
+
* Browser only. Remember `token` for this page session (sessionStorage) and route this client's
|
|
275
|
+
* own accessors through the session while it is active. `null` leaves the session.
|
|
276
|
+
* On servers use `session()` or `@nanoflags/sdk/node` instead: one client serves many requests.
|
|
277
|
+
*/
|
|
278
|
+
useSession(token: string | null): Promise<SessionEvaluator>;
|
|
279
|
+
/** Browser only. `{ "x-nanoflags-session": token }` while a page session is set, otherwise `{}`. */
|
|
280
|
+
sessionHeaders(): Record<string, string>;
|
|
281
|
+
on(event: "update", cb: (e: UpdateEvent) => void): () => void;
|
|
282
|
+
on(event: "error", cb: (e: Error) => void): () => void;
|
|
283
|
+
/** Force a revalidation now. Resolves when it finished (successfully or not). */
|
|
284
|
+
refresh(): Promise<void>;
|
|
285
|
+
/** Send queued telemetry now. */
|
|
286
|
+
flush(): Promise<void>;
|
|
287
|
+
/** Stops timers, the stream and telemetry. Evaluations keep working on the last bundle. */
|
|
288
|
+
close(): void;
|
|
289
|
+
/** For external-store bindings (React): called on every bundle or status change. */
|
|
290
|
+
subscribe(listener: () => void): () => void;
|
|
291
|
+
/** Monotonic counter that changes whenever `subscribe` listeners fire. */
|
|
292
|
+
readonly version: number;
|
|
293
|
+
}
|
|
294
|
+
declare class NanoFlagsError extends Error {
|
|
295
|
+
readonly code: "network" | "unauthorized" | "http" | "invalid_bundle" | "store" | "config" | "signature" | "session" | "engine" | "environment_deleted";
|
|
296
|
+
readonly httpStatus?: number | undefined;
|
|
297
|
+
constructor(message: string, code: "network" | "unauthorized" | "http" | "invalid_bundle" | "store" | "config" | "signature" | "session" | "engine" | "environment_deleted", httpStatus?: number | undefined);
|
|
298
|
+
}
|
|
299
|
+
/** A session token is opaque; it only has to be safe to put in a header. */
|
|
300
|
+
declare function isSessionToken(v: unknown): v is string;
|
|
301
|
+
declare function createClient(options: ClientOptions): NanoFlagsClient;
|
|
302
|
+
export { Store as C, JsonValue as D, Evaluation as E, Reason as O, VerifyOptions as S, Context as T, WebSocketLike as _, FlagEvaluator as a, OFFICIAL_EDGE_URL as b, NanoFlagsError as c, SUPPORTED_ENGINE_VERSION as d, SessionEvaluator as f, WebSocketConstructor as g, UpdateEvent as h, EventsOptions as i, SDK_VERSION as l, Transport as m, ClientOptions as n, LIVE_PROTOCOL as o, SessionOptions as p, ClientStatus as r, NanoFlagsClient as s, CLOSE_ENVIRONMENT_DELETED as t, SESSION_HEADER as u, createClient as v, Bundle as w, OFFICIAL_SIGNING_KEYS as x, isSessionToken as y };
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
type FlagType = "boolean" | "string" | "number" | "json";
|
|
2
|
+
type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
3
|
+
[k: string]: JsonValue;
|
|
4
|
+
};
|
|
5
|
+
type Operator = "eq" | "neq" | "in" | "not_in" | "contains" | "starts_with" | "ends_with" | "gt" | "gte" | "lt" | "lte" | "exists" | "not_exists" | "segment" | "not_segment";
|
|
6
|
+
interface Condition {
|
|
7
|
+
/** Context attribute name, e.g. "region". Ignored for segment operators. */
|
|
8
|
+
attribute: string;
|
|
9
|
+
op: Operator;
|
|
10
|
+
/** Comparison value. Array for in/not_in; segment key for segment operators. */
|
|
11
|
+
value?: JsonValue;
|
|
12
|
+
}
|
|
13
|
+
type Serve = {
|
|
14
|
+
type: "fixed";
|
|
15
|
+
value: JsonValue;
|
|
16
|
+
} | {
|
|
17
|
+
type: "rollout";
|
|
18
|
+
/** 0–100, up to two decimals. */
|
|
19
|
+
percentage: number;
|
|
20
|
+
/** Value for contexts inside the allocation. */
|
|
21
|
+
value: JsonValue;
|
|
22
|
+
/** Value for matching contexts outside the allocation. */
|
|
23
|
+
otherwise: JsonValue;
|
|
24
|
+
/** Context attribute used for bucketing. Defaults to "key". */
|
|
25
|
+
bucketBy?: string;
|
|
26
|
+
/** Documented seed. Defaults to the flag key, so allocations are independent per flag. */
|
|
27
|
+
seed?: string;
|
|
28
|
+
};
|
|
29
|
+
interface Rule {
|
|
30
|
+
id: string;
|
|
31
|
+
description?: string;
|
|
32
|
+
match: "all" | "any";
|
|
33
|
+
conditions: Condition[];
|
|
34
|
+
serve: Serve;
|
|
35
|
+
}
|
|
36
|
+
interface FlagConfig {
|
|
37
|
+
type: FlagType;
|
|
38
|
+
/** When false the flag short-circuits to `off`. */
|
|
39
|
+
enabled: boolean;
|
|
40
|
+
rules: Rule[];
|
|
41
|
+
/** Served when the flag is enabled and no rule matches. */
|
|
42
|
+
default: JsonValue;
|
|
43
|
+
/** Served when the flag is disabled. */
|
|
44
|
+
off: JsonValue;
|
|
45
|
+
/** Only client-exposed flags are included in bundles served to browser keys. */
|
|
46
|
+
clientExposed?: boolean;
|
|
47
|
+
}
|
|
48
|
+
interface Segment {
|
|
49
|
+
match: "all" | "any";
|
|
50
|
+
conditions: Condition[];
|
|
51
|
+
}
|
|
52
|
+
interface Bundle {
|
|
53
|
+
schema: 1;
|
|
54
|
+
/**
|
|
55
|
+
* Engine version the bundle was produced for (`ENGINE_VERSION` of the publisher). Absent in bundles from before it
|
|
56
|
+
* existed (treated as 1). SDKs refuse a bundle whose `engine` is newer than the engine they ship.
|
|
57
|
+
*/
|
|
58
|
+
engine?: number;
|
|
59
|
+
project: string;
|
|
60
|
+
environment: string;
|
|
61
|
+
/** Published revision number. 0 means "draft / never published". */
|
|
62
|
+
revision: number;
|
|
63
|
+
flags: Record<string, FlagConfig>;
|
|
64
|
+
segments: Record<string, Segment>;
|
|
65
|
+
}
|
|
66
|
+
/** Attributes supplied by the application. `key` is the stable identity used for bucketing. */
|
|
67
|
+
type Context = {
|
|
68
|
+
key?: string;
|
|
69
|
+
} & Record<string, JsonValue | undefined>;
|
|
70
|
+
type Reason = "rule_match" | "default" | "off" | "flag_not_found" | "error";
|
|
71
|
+
interface TraceStep {
|
|
72
|
+
kind: "config" | "rule" | "allocation" | "result";
|
|
73
|
+
title: string;
|
|
74
|
+
detail: string;
|
|
75
|
+
matched?: boolean;
|
|
76
|
+
}
|
|
77
|
+
interface Evaluation<T = JsonValue> {
|
|
78
|
+
flagKey: string;
|
|
79
|
+
value: T;
|
|
80
|
+
reason: Reason;
|
|
81
|
+
/** Zero-based index of the matching rule. */
|
|
82
|
+
ruleIndex?: number;
|
|
83
|
+
ruleId?: string;
|
|
84
|
+
/** For rollout rules: whether the context fell inside the allocation, and its bucket (0–99.99). */
|
|
85
|
+
inRollout?: boolean;
|
|
86
|
+
bucket?: number;
|
|
87
|
+
revision: number;
|
|
88
|
+
trace: TraceStep[];
|
|
89
|
+
error?: string;
|
|
90
|
+
}
|
|
91
|
+
/** Persistence for the last bundle. Values are opaque strings owned by the SDK. */
|
|
92
|
+
interface Store {
|
|
93
|
+
get(): Promise<string | null>;
|
|
94
|
+
set(value: string): Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Bundle signature verification (Ed25519 over a canonical string, WebCrypto only).
|
|
98
|
+
*
|
|
99
|
+
* canonical = "nanoflags-bundle-v1\n<environment_id>\n<revision>\n<checksum>\n<sha256 hex of the bundle JSON text>"
|
|
100
|
+
*
|
|
101
|
+
* Only PUBLIC keys are handled here. Private and admin keys never enter the SDK.
|
|
102
|
+
*/
|
|
103
|
+
interface VerifyOptions {
|
|
104
|
+
/**
|
|
105
|
+
* Public Ed25519 keys as JWK (`{ kty: "OKP", crv: "Ed25519", x, kid? }`), or `"fetch"` to load them
|
|
106
|
+
* once from `GET /v1/keys` on the configured edge (again, at most once a minute, when a bundle names an unknown
|
|
107
|
+
* key id). Pinning keys in your build is stronger than `"fetch"`: fetched keys are only as trustworthy as the
|
|
108
|
+
* connection they arrived over. Omitted: the embedded production keys for `https://edge.nanoflags.io`, `"fetch"`
|
|
109
|
+
* for any other edge.
|
|
110
|
+
*/
|
|
111
|
+
publicKeys?: readonly JsonWebKey[] | "fetch";
|
|
112
|
+
/**
|
|
113
|
+
* Also reject bundles that carry no signature (the edge's unsigned fallback, `X-NanoFlags-Signed: false`): the SDK
|
|
114
|
+
* keeps its bundle and fetches again shortly instead. Default true for `https://edge.nanoflags.io`, false otherwise.
|
|
115
|
+
*/
|
|
116
|
+
require?: boolean;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The hosted NanoFlags edge and the public halves of its bundle-signing keys (Ed25519, safe to embed).
|
|
120
|
+
*
|
|
121
|
+
* With `baseUrl` equal to `OFFICIAL_EDGE_URL` the SDK verifies every bundle against these keys by default
|
|
122
|
+
* (`verify.require` defaults to true there). A bundle signed with a key id that is not listed here — a rotation that
|
|
123
|
+
* happened after this SDK version was built — makes the SDK load `GET /v1/keys` from the edge once and verify against
|
|
124
|
+
* the keys it lists as well. Rotation procedure: RUNTIME.md, "Signing-key rotation".
|
|
125
|
+
*/
|
|
126
|
+
declare const OFFICIAL_EDGE_URL = "https://edge.nanoflags.io";
|
|
127
|
+
declare const OFFICIAL_SIGNING_KEYS: readonly (JsonWebKey & {
|
|
128
|
+
kid: string;
|
|
129
|
+
})[];
|
|
130
|
+
declare const SDK_VERSION = "0.4.0";
|
|
131
|
+
/** Newest bundle format (`bundle.engine`) this SDK can evaluate. Newer bundles are refused; the previous one stays in use. */
|
|
132
|
+
declare const SUPPORTED_ENGINE_VERSION = 1;
|
|
133
|
+
/** WebSocket close code of the edge for an environment that was deleted: the SDK stops reconnecting. */
|
|
134
|
+
declare const CLOSE_ENVIRONMENT_DELETED = 4004;
|
|
135
|
+
/** Header that carries a test-session token between services. */
|
|
136
|
+
declare const SESSION_HEADER = "x-nanoflags-session";
|
|
137
|
+
type ClientStatus = "not-ready" | "ready" | "stale";
|
|
138
|
+
/** How updates currently reach the client: pushed over the live WebSocket, announced over SSE, or polled. */
|
|
139
|
+
type Transport = "live" | "stream" | "poll";
|
|
140
|
+
/** WebSocket subprotocol of `/v1/live`. The key travels as a second protocol entry, never in the URL. */
|
|
141
|
+
declare const LIVE_PROTOCOL = "nanoflags.v1";
|
|
142
|
+
/** The part of the WHATWG WebSocket the SDK uses (browsers, Node ≥ 22, Deno, Bun, the `ws` package). */
|
|
143
|
+
interface WebSocketLike {
|
|
144
|
+
send(data: string): void;
|
|
145
|
+
close(code?: number, reason?: string): void;
|
|
146
|
+
onopen: ((event: any) => any) | null;
|
|
147
|
+
onmessage: ((event: any) => any) | null;
|
|
148
|
+
onclose: ((event: any) => any) | null;
|
|
149
|
+
onerror: ((event: any) => any) | null;
|
|
150
|
+
}
|
|
151
|
+
type WebSocketConstructor = new (url: string, protocols?: string | string[]) => WebSocketLike;
|
|
152
|
+
interface EventsOptions {
|
|
153
|
+
/** Default true. */
|
|
154
|
+
enabled?: boolean;
|
|
155
|
+
/** Fraction of evaluations reported, 0–1. Default 0.1. */
|
|
156
|
+
sampleRate?: number;
|
|
157
|
+
/** Default 10000. How often queued events are sent. */
|
|
158
|
+
flushIntervalMs?: number;
|
|
159
|
+
/**
|
|
160
|
+
* Default 60000. While no events are queued, the service report ("this service runs revision N")
|
|
161
|
+
* goes out at this interval instead of on every flush interval.
|
|
162
|
+
*/
|
|
163
|
+
reportIntervalMs?: number;
|
|
164
|
+
/**
|
|
165
|
+
* Decides what part of the evaluation context leaves the process with a sampled event.
|
|
166
|
+
* Default: no attribute VALUES are sent — only the names of the attributes that the flag's
|
|
167
|
+
* rules reference and that were present, mapped to the value's type (e.g. `{ region: "string" }`).
|
|
168
|
+
*/
|
|
169
|
+
redact?: (ctx: Context) => Record<string, JsonValue | undefined>;
|
|
170
|
+
/** Random source for sampling; injectable for tests. */
|
|
171
|
+
random?: () => number;
|
|
172
|
+
}
|
|
173
|
+
interface ClientOptions {
|
|
174
|
+
/** `nf_srv_…` on servers, `nf_pub_…` in browsers. Never ship a server key to a browser. */
|
|
175
|
+
sdkKey: string;
|
|
176
|
+
/** Base URL of the NanoFlags edge, e.g. `https://flags.example.com`. */
|
|
177
|
+
baseUrl: string;
|
|
178
|
+
/** Name shown in "which revision is this service running". */
|
|
179
|
+
service?: string;
|
|
180
|
+
/** Default 30000. `0` disables polling. */
|
|
181
|
+
pollIntervalMs?: number;
|
|
182
|
+
/**
|
|
183
|
+
* Default true. Receive updates without polling: over the live WebSocket when the runtime has
|
|
184
|
+
* one, otherwise (or when the socket cannot be established) over SSE. `false` disables both.
|
|
185
|
+
*/
|
|
186
|
+
streaming?: boolean;
|
|
187
|
+
/** Default true. `false` skips the live WebSocket and uses SSE + polling as SDK 0.2 did. */
|
|
188
|
+
live?: boolean;
|
|
189
|
+
/** Default 300000. Safety-poll interval while the live socket is healthy (`pollIntervalMs` applies otherwise; `pollIntervalMs: 0` disables both). */
|
|
190
|
+
livePollIntervalMs?: number;
|
|
191
|
+
/** WebSocket implementation. Default: the global `WebSocket` (browsers, Node ≥ 22). Without one the SDK uses SSE + polling. */
|
|
192
|
+
webSocket?: WebSocketConstructor;
|
|
193
|
+
/** A bundle obtained elsewhere (e.g. embedded at build time or passed from the server). */
|
|
194
|
+
bootstrap?: Bundle;
|
|
195
|
+
/** Persistence. Default: IndexedDB in browsers, none elsewhere. `false` disables it. */
|
|
196
|
+
store?: Store | false;
|
|
197
|
+
events?: EventsOptions | false;
|
|
198
|
+
/**
|
|
199
|
+
* Verify bundle signatures before a new bundle replaces the current one. A bundle whose signature
|
|
200
|
+
* does not verify is rejected: the previous bundle stays in use and an `error` (`code: "signature"`)
|
|
201
|
+
* is emitted. Without `require`, bundles the edge marks as unsigned are still accepted.
|
|
202
|
+
*
|
|
203
|
+
* Default: with `baseUrl` = `https://edge.nanoflags.io` the SDK verifies against the embedded production keys
|
|
204
|
+
* (`OFFICIAL_SIGNING_KEYS`, plus `GET /v1/keys` once when a bundle names an unknown key id) with `require: true`;
|
|
205
|
+
* with any other `baseUrl` nothing is verified unless configured. `false` turns verification off explicitly.
|
|
206
|
+
*/
|
|
207
|
+
verify?: VerifyOptions | false;
|
|
208
|
+
fetch?: typeof fetch;
|
|
209
|
+
}
|
|
210
|
+
/** The flag accessors shared by the client and by session-scoped evaluators. */
|
|
211
|
+
interface FlagEvaluator {
|
|
212
|
+
boolean(key: string, fallback: boolean, ctx?: Context): boolean;
|
|
213
|
+
string(key: string, fallback: string, ctx?: Context): string;
|
|
214
|
+
number(key: string, fallback: number, ctx?: Context): number;
|
|
215
|
+
json<T extends JsonValue = JsonValue>(key: string, fallback: T, ctx?: Context): T;
|
|
216
|
+
/** Full engine result (value, reason, matched rule, trace). No type check is applied. */
|
|
217
|
+
evaluate<T extends JsonValue = JsonValue>(key: string, fallback: T, ctx?: Context): Evaluation<T>;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Evaluator bound to one test session. While `active`, flags are evaluated against the session's
|
|
221
|
+
* pinned bundle with the context `{ ...session.context, ...ctx }` and sampled events carry the
|
|
222
|
+
* session id. When the session is unknown, not permitted for this service, or expired, it evaluates
|
|
223
|
+
* exactly like the client (`active` is false). It never throws.
|
|
224
|
+
*/
|
|
225
|
+
interface SessionEvaluator extends FlagEvaluator {
|
|
226
|
+
/** True while the session is known and has not expired. Re-evaluated on every read. */
|
|
227
|
+
readonly active: boolean;
|
|
228
|
+
/** Session id, or null when the session could not be resolved. */
|
|
229
|
+
readonly id: string | null;
|
|
230
|
+
/** ISO timestamp, or null when the session could not be resolved. */
|
|
231
|
+
readonly expiresAt: string | null;
|
|
232
|
+
/** Revision evaluations currently run against (the pinned one while active, otherwise the client's). */
|
|
233
|
+
readonly revision: number | null;
|
|
234
|
+
}
|
|
235
|
+
interface SessionOptions {
|
|
236
|
+
/** Service name sent as `X-NanoFlags-Service`. Defaults to the client's `service`. */
|
|
237
|
+
service?: string;
|
|
238
|
+
}
|
|
239
|
+
interface UpdateEvent {
|
|
240
|
+
revision: number;
|
|
241
|
+
previousRevision: number | null;
|
|
242
|
+
checksum: string | null;
|
|
243
|
+
source: "network" | "store" | "bootstrap";
|
|
244
|
+
/**
|
|
245
|
+
* Milliseconds from the commit of the revision in the database to this event — only for revisions
|
|
246
|
+
* pushed over the live socket (`transport: "live"`) that carry the commit time; otherwise null.
|
|
247
|
+
* It compares the database's clock with this machine's, so it is as accurate as their clocks agree.
|
|
248
|
+
*/
|
|
249
|
+
latencyMs: number | null;
|
|
250
|
+
/** How this bundle arrived: pushed (`live`), fetched after an SSE notification (`stream`), or anything else (`poll`). */
|
|
251
|
+
transport: Transport;
|
|
252
|
+
}
|
|
253
|
+
interface NanoFlagsClient {
|
|
254
|
+
/** Resolves once a usable bundle is loaded, or once the first load attempt has finished without one. Never rejects. */
|
|
255
|
+
ready(): Promise<void>;
|
|
256
|
+
readonly status: ClientStatus;
|
|
257
|
+
/** Revision of the bundle in use, or null when none is loaded. */
|
|
258
|
+
readonly revision: number | null;
|
|
259
|
+
/** How updates reach this client right now: `live` while the WebSocket is open, `stream` while SSE is in use, else `poll`. */
|
|
260
|
+
readonly transport: Transport;
|
|
261
|
+
boolean(key: string, fallback: boolean, ctx?: Context): boolean;
|
|
262
|
+
string(key: string, fallback: string, ctx?: Context): string;
|
|
263
|
+
number(key: string, fallback: number, ctx?: Context): number;
|
|
264
|
+
json<T extends JsonValue = JsonValue>(key: string, fallback: T, ctx?: Context): T;
|
|
265
|
+
/** Full engine result (value, reason, matched rule, trace). No type check is applied. */
|
|
266
|
+
evaluate<T extends JsonValue = JsonValue>(key: string, fallback: T, ctx?: Context): Evaluation<T>;
|
|
267
|
+
/**
|
|
268
|
+
* Resolve a test session (`GET /v1/session`, once per token until it expires) and return an
|
|
269
|
+
* evaluator scoped to it. Never rejects: an unknown or expired session yields an evaluator
|
|
270
|
+
* whose `active` is false and that behaves like the client.
|
|
271
|
+
*/
|
|
272
|
+
session(token: string | null | undefined, options?: SessionOptions): Promise<SessionEvaluator>;
|
|
273
|
+
/**
|
|
274
|
+
* Browser only. Remember `token` for this page session (sessionStorage) and route this client's
|
|
275
|
+
* own accessors through the session while it is active. `null` leaves the session.
|
|
276
|
+
* On servers use `session()` or `@nanoflags/sdk/node` instead: one client serves many requests.
|
|
277
|
+
*/
|
|
278
|
+
useSession(token: string | null): Promise<SessionEvaluator>;
|
|
279
|
+
/** Browser only. `{ "x-nanoflags-session": token }` while a page session is set, otherwise `{}`. */
|
|
280
|
+
sessionHeaders(): Record<string, string>;
|
|
281
|
+
on(event: "update", cb: (e: UpdateEvent) => void): () => void;
|
|
282
|
+
on(event: "error", cb: (e: Error) => void): () => void;
|
|
283
|
+
/** Force a revalidation now. Resolves when it finished (successfully or not). */
|
|
284
|
+
refresh(): Promise<void>;
|
|
285
|
+
/** Send queued telemetry now. */
|
|
286
|
+
flush(): Promise<void>;
|
|
287
|
+
/** Stops timers, the stream and telemetry. Evaluations keep working on the last bundle. */
|
|
288
|
+
close(): void;
|
|
289
|
+
/** For external-store bindings (React): called on every bundle or status change. */
|
|
290
|
+
subscribe(listener: () => void): () => void;
|
|
291
|
+
/** Monotonic counter that changes whenever `subscribe` listeners fire. */
|
|
292
|
+
readonly version: number;
|
|
293
|
+
}
|
|
294
|
+
declare class NanoFlagsError extends Error {
|
|
295
|
+
readonly code: "network" | "unauthorized" | "http" | "invalid_bundle" | "store" | "config" | "signature" | "session" | "engine" | "environment_deleted";
|
|
296
|
+
readonly httpStatus?: number | undefined;
|
|
297
|
+
constructor(message: string, code: "network" | "unauthorized" | "http" | "invalid_bundle" | "store" | "config" | "signature" | "session" | "engine" | "environment_deleted", httpStatus?: number | undefined);
|
|
298
|
+
}
|
|
299
|
+
/** A session token is opaque; it only has to be safe to put in a header. */
|
|
300
|
+
declare function isSessionToken(v: unknown): v is string;
|
|
301
|
+
declare function createClient(options: ClientOptions): NanoFlagsClient;
|
|
302
|
+
export { Store as C, JsonValue as D, Evaluation as E, Reason as O, VerifyOptions as S, Context as T, WebSocketLike as _, FlagEvaluator as a, OFFICIAL_EDGE_URL as b, NanoFlagsError as c, SUPPORTED_ENGINE_VERSION as d, SessionEvaluator as f, WebSocketConstructor as g, UpdateEvent as h, EventsOptions as i, SDK_VERSION as l, Transport as m, ClientOptions as n, LIVE_PROTOCOL as o, SessionOptions as p, ClientStatus as r, NanoFlagsClient as s, CLOSE_ENVIRONMENT_DELETED as t, SESSION_HEADER as u, createClient as v, Bundle as w, OFFICIAL_SIGNING_KEYS as x, isSessionToken as y };
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_src = require("./src-IVd-Wps4.cjs");
|
|
3
|
+
exports.CLOSE_ENVIRONMENT_DELETED = require_src.CLOSE_ENVIRONMENT_DELETED;
|
|
4
|
+
exports.LIVE_PROTOCOL = require_src.LIVE_PROTOCOL;
|
|
5
|
+
exports.NanoFlagsError = require_src.NanoFlagsError;
|
|
6
|
+
exports.OFFICIAL_EDGE_URL = require_src.OFFICIAL_EDGE_URL;
|
|
7
|
+
exports.OFFICIAL_SIGNING_KEYS = require_src.OFFICIAL_SIGNING_KEYS;
|
|
8
|
+
exports.SDK_VERSION = require_src.SDK_VERSION;
|
|
9
|
+
exports.SESSION_HEADER = require_src.SESSION_HEADER;
|
|
10
|
+
exports.SUPPORTED_ENGINE_VERSION = require_src.SUPPORTED_ENGINE_VERSION;
|
|
11
|
+
exports.createClient = require_src.createClient;
|
|
12
|
+
exports.isSessionToken = require_src.isSessionToken;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @nanoflags/sdk — isomorphic core.
|
|
3
|
+
*
|
|
4
|
+
* Flags are evaluated locally and synchronously against an in-memory bundle. The network is only
|
|
5
|
+
* used in the background: to load the bundle, to learn about new revisions, and to send sampled
|
|
6
|
+
* telemetry. A flag accessor never performs I/O and never throws.
|
|
7
|
+
*
|
|
8
|
+
* New revisions arrive over one of three transports, best first: the live WebSocket (`/v1/live`,
|
|
9
|
+
* the edge pushes the signed bundle itself — no request follows), the SSE stream (`/v1/stream`,
|
|
10
|
+
* a notification followed by a conditional fetch), and polling (`/v1/bundle`).
|
|
11
|
+
*/
|
|
12
|
+
import { C as Store, D as JsonValue, E as Evaluation, O as Reason, S as VerifyOptions, T as Context, _ as WebSocketLike, a as FlagEvaluator, b as OFFICIAL_EDGE_URL, c as NanoFlagsError, d as SUPPORTED_ENGINE_VERSION, f as SessionEvaluator, g as WebSocketConstructor, h as UpdateEvent, i as EventsOptions, l as SDK_VERSION, m as Transport, n as ClientOptions, o as LIVE_PROTOCOL, p as SessionOptions, r as ClientStatus, s as NanoFlagsClient, t as CLOSE_ENVIRONMENT_DELETED, u as SESSION_HEADER, v as createClient, w as Bundle, x as OFFICIAL_SIGNING_KEYS, y as isSessionToken } from "./index-D5qa8ji-.cjs";
|
|
13
|
+
export { type Bundle, CLOSE_ENVIRONMENT_DELETED, ClientOptions, ClientStatus, type Context, type Evaluation, EventsOptions, FlagEvaluator, type JsonValue, LIVE_PROTOCOL, NanoFlagsClient, NanoFlagsError, OFFICIAL_EDGE_URL, OFFICIAL_SIGNING_KEYS, type Reason, SDK_VERSION, SESSION_HEADER, SUPPORTED_ENGINE_VERSION, SessionEvaluator, SessionOptions, type Store, Transport, UpdateEvent, type VerifyOptions, WebSocketConstructor, WebSocketLike, createClient, isSessionToken };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @nanoflags/sdk — isomorphic core.
|
|
3
|
+
*
|
|
4
|
+
* Flags are evaluated locally and synchronously against an in-memory bundle. The network is only
|
|
5
|
+
* used in the background: to load the bundle, to learn about new revisions, and to send sampled
|
|
6
|
+
* telemetry. A flag accessor never performs I/O and never throws.
|
|
7
|
+
*
|
|
8
|
+
* New revisions arrive over one of three transports, best first: the live WebSocket (`/v1/live`,
|
|
9
|
+
* the edge pushes the signed bundle itself — no request follows), the SSE stream (`/v1/stream`,
|
|
10
|
+
* a notification followed by a conditional fetch), and polling (`/v1/bundle`).
|
|
11
|
+
*/
|
|
12
|
+
import { C as Store, D as JsonValue, E as Evaluation, O as Reason, S as VerifyOptions, T as Context, _ as WebSocketLike, a as FlagEvaluator, b as OFFICIAL_EDGE_URL, c as NanoFlagsError, d as SUPPORTED_ENGINE_VERSION, f as SessionEvaluator, g as WebSocketConstructor, h as UpdateEvent, i as EventsOptions, l as SDK_VERSION, m as Transport, n as ClientOptions, o as LIVE_PROTOCOL, p as SessionOptions, r as ClientStatus, s as NanoFlagsClient, t as CLOSE_ENVIRONMENT_DELETED, u as SESSION_HEADER, v as createClient, w as Bundle, x as OFFICIAL_SIGNING_KEYS, y as isSessionToken } from "./index-D5qa8ji-.js";
|
|
13
|
+
export { type Bundle, CLOSE_ENVIRONMENT_DELETED, ClientOptions, ClientStatus, type Context, type Evaluation, EventsOptions, FlagEvaluator, type JsonValue, LIVE_PROTOCOL, NanoFlagsClient, NanoFlagsError, OFFICIAL_EDGE_URL, OFFICIAL_SIGNING_KEYS, type Reason, SDK_VERSION, SESSION_HEADER, SUPPORTED_ENGINE_VERSION, SessionEvaluator, SessionOptions, type Store, Transport, UpdateEvent, type VerifyOptions, WebSocketConstructor, WebSocketLike, createClient, isSessionToken };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { t as CLOSE_ENVIRONMENT_DELETED, n as LIVE_PROTOCOL, r as NanoFlagsError, l as OFFICIAL_EDGE_URL, u as OFFICIAL_SIGNING_KEYS, i as SDK_VERSION, a as SESSION_HEADER, o as SUPPORTED_ENGINE_VERSION, s as createClient, c as isSessionToken } from "./src-CVTvEKbT.js";
|