@nebulr-group/bridge-auth-core 0.1.2 → 0.4.0-beta.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/dist/billing/bridge-subscription.d.ts +71 -0
- package/dist/billing/bridge-subscription.d.ts.map +1 -0
- package/dist/billing/bridge-subscription.js +209 -0
- package/dist/billing/bridge-subscription.js.map +1 -0
- package/dist/billing/entitlements-store.d.ts +61 -0
- package/dist/billing/entitlements-store.d.ts.map +1 -0
- package/dist/billing/entitlements-store.js +127 -0
- package/dist/billing/entitlements-store.js.map +1 -0
- package/dist/billing/fetch-billing-state.d.ts +9 -0
- package/dist/billing/fetch-billing-state.d.ts.map +1 -0
- package/dist/billing/fetch-billing-state.js +22 -0
- package/dist/billing/fetch-billing-state.js.map +1 -0
- package/dist/billing/lock-signal.d.ts +6 -0
- package/dist/billing/lock-signal.d.ts.map +1 -0
- package/dist/billing/lock-signal.js +8 -0
- package/dist/billing/lock-signal.js.map +1 -0
- package/dist/billing/quota-store.d.ts +86 -0
- package/dist/billing/quota-store.d.ts.map +1 -0
- package/dist/billing/quota-store.js +180 -0
- package/dist/billing/quota-store.js.map +1 -0
- package/dist/billing/types.d.ts +64 -0
- package/dist/billing/types.d.ts.map +1 -0
- package/dist/billing/types.js +49 -0
- package/dist/billing/types.js.map +1 -0
- package/dist/billing/use-bridge.d.ts +131 -0
- package/dist/billing/use-bridge.d.ts.map +1 -0
- package/dist/billing/use-bridge.js +181 -0
- package/dist/billing/use-bridge.js.map +1 -0
- package/dist/bridge-auth.d.ts +36 -1
- package/dist/bridge-auth.d.ts.map +1 -1
- package/dist/bridge-auth.js +57 -3
- package/dist/bridge-auth.js.map +1 -1
- package/dist/direct-auth.d.ts +1 -0
- package/dist/direct-auth.d.ts.map +1 -1
- package/dist/direct-auth.js +7 -0
- package/dist/direct-auth.js.map +1 -1
- package/dist/errors.d.ts +11 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +14 -0
- package/dist/errors.js.map +1 -1
- package/dist/flags/attribute-providers.d.ts +229 -0
- package/dist/flags/attribute-providers.d.ts.map +1 -0
- package/dist/flags/attribute-providers.js +375 -0
- package/dist/flags/attribute-providers.js.map +1 -0
- package/dist/flags/dev-attribute-provider.d.ts +67 -0
- package/dist/flags/dev-attribute-provider.d.ts.map +1 -0
- package/dist/flags/dev-attribute-provider.js +200 -0
- package/dist/flags/dev-attribute-provider.js.map +1 -0
- package/dist/flags/evaluator.d.ts +58 -0
- package/dist/flags/evaluator.d.ts.map +1 -0
- package/dist/flags/evaluator.js +160 -0
- package/dist/flags/evaluator.js.map +1 -0
- package/dist/flags/flag.d.ts +199 -0
- package/dist/flags/flag.d.ts.map +1 -0
- package/dist/flags/flag.js +337 -0
- package/dist/flags/flag.js.map +1 -0
- package/dist/flags/identity.d.ts +77 -0
- package/dist/flags/identity.d.ts.map +1 -0
- package/dist/flags/identity.js +134 -0
- package/dist/flags/identity.js.map +1 -0
- package/dist/flags/index.d.ts +20 -0
- package/dist/flags/index.d.ts.map +1 -0
- package/dist/flags/index.js +21 -0
- package/dist/flags/index.js.map +1 -0
- package/dist/flags/operators.d.ts +63 -0
- package/dist/flags/operators.d.ts.map +1 -0
- package/dist/flags/operators.js +299 -0
- package/dist/flags/operators.js.map +1 -0
- package/dist/flags/propagation.d.ts +16 -0
- package/dist/flags/propagation.d.ts.map +1 -0
- package/dist/flags/propagation.js +107 -0
- package/dist/flags/propagation.js.map +1 -0
- package/dist/flags/realtime.d.ts +328 -0
- package/dist/flags/realtime.d.ts.map +1 -0
- package/dist/flags/realtime.js +504 -0
- package/dist/flags/realtime.js.map +1 -0
- package/dist/flags/runtime-mode.d.ts +32 -0
- package/dist/flags/runtime-mode.d.ts.map +1 -0
- package/dist/flags/runtime-mode.js +84 -0
- package/dist/flags/runtime-mode.js.map +1 -0
- package/dist/flags/telemetry.d.ts +79 -0
- package/dist/flags/telemetry.d.ts.map +1 -0
- package/dist/flags/telemetry.js +286 -0
- package/dist/flags/telemetry.js.map +1 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +11 -1
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +14 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/management-types.d.ts +38 -0
- package/dist/management-types.d.ts.map +1 -1
- package/dist/route-guard.d.ts.map +1 -1
- package/dist/route-guard.js +15 -5
- package/dist/route-guard.js.map +1 -1
- package/dist/token-manager.d.ts +3 -1
- package/dist/token-manager.d.ts.map +1 -1
- package/dist/token-manager.js +10 -6
- package/dist/token-manager.js.map +1 -1
- package/dist/types.d.ts +10 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/usage/index.d.ts +3 -0
- package/dist/usage/index.d.ts.map +1 -0
- package/dist/usage/index.js +4 -0
- package/dist/usage/index.js.map +1 -0
- package/dist/usage/storage/durable-storage.d.ts +47 -0
- package/dist/usage/storage/durable-storage.d.ts.map +1 -0
- package/dist/usage/storage/durable-storage.js +27 -0
- package/dist/usage/storage/durable-storage.js.map +1 -0
- package/dist/usage/storage/index.d.ts +7 -0
- package/dist/usage/storage/index.d.ts.map +1 -0
- package/dist/usage/storage/index.js +28 -0
- package/dist/usage/storage/index.js.map +1 -0
- package/dist/usage/storage/indexeddb-storage.d.ts +18 -0
- package/dist/usage/storage/indexeddb-storage.d.ts.map +1 -0
- package/dist/usage/storage/indexeddb-storage.js +159 -0
- package/dist/usage/storage/indexeddb-storage.js.map +1 -0
- package/dist/usage/storage/node-fs-storage.d.ts +29 -0
- package/dist/usage/storage/node-fs-storage.d.ts.map +1 -0
- package/dist/usage/storage/node-fs-storage.js +180 -0
- package/dist/usage/storage/node-fs-storage.js.map +1 -0
- package/dist/usage/storage/noop-storage.d.ts +17 -0
- package/dist/usage/storage/noop-storage.d.ts.map +1 -0
- package/dist/usage/storage/noop-storage.js +67 -0
- package/dist/usage/storage/noop-storage.js.map +1 -0
- package/dist/usage/usage-reporter.d.ts +64 -0
- package/dist/usage/usage-reporter.d.ts.map +1 -0
- package/dist/usage/usage-reporter.js +234 -0
- package/dist/usage/usage-reporter.js.map +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
// bridge.flag(key, default) — the canonical SDK call (TBP-160).
|
|
2
|
+
//
|
|
3
|
+
// One method, one signature. The TypeScript return type matches the default
|
|
4
|
+
// value's type (boolean / string / number / structured), so callers don't
|
|
5
|
+
// need a separate cast.
|
|
6
|
+
//
|
|
7
|
+
// Local-first evaluation:
|
|
8
|
+
// 1. Look up the flag in the in-memory cache
|
|
9
|
+
// 2. If absent → return the developer's `defaultValue` (and emit a
|
|
10
|
+
// "discovered" hook so the SDK can register the key with bridge-api)
|
|
11
|
+
// 3. If present → evaluate locally against the dev-supplied context
|
|
12
|
+
// 4. Always emit an `onEval` hook so the SDK can batch eval telemetry
|
|
13
|
+
//
|
|
14
|
+
// Hooks are pluggable so this module stays platform-agnostic. The actual
|
|
15
|
+
// wiring (HTTP batcher, fetch client, etc.) is the SDK integration's job
|
|
16
|
+
// — see TBP-157 / TBP-156 for the implementations.
|
|
17
|
+
import { evaluateRule, } from './evaluator.js';
|
|
18
|
+
import { AttributeProviderRegistry, } from './attribute-providers.js';
|
|
19
|
+
export class BridgeFlags {
|
|
20
|
+
cache = new Map();
|
|
21
|
+
context = { attributes: {} };
|
|
22
|
+
hooks = {};
|
|
23
|
+
discoveredKeys = new Set();
|
|
24
|
+
/** Per-runtime dedup for attribute observations: `${key}::${canonicalValue}`. */
|
|
25
|
+
observedAttributeKeys = new Set();
|
|
26
|
+
attributeDeclarations = new Map();
|
|
27
|
+
mode = 'frontend';
|
|
28
|
+
serverInstanceIdValue;
|
|
29
|
+
missingIdentityWarned = new Set();
|
|
30
|
+
/** Billing 2.0 US-10 (TBP-262): self-report `bridge.flag_evaluations` per eval. */
|
|
31
|
+
usageReporter;
|
|
32
|
+
/**
|
|
33
|
+
* Phase 1 / US-13 (TBP-293, TBP-294) — AttributeProvider registry consulted
|
|
34
|
+
* on every flag eval. Bridge-managed providers (`bridge:auth`,
|
|
35
|
+
* `bridge:billing`) are auto-registered by framework SDKs; apps register
|
|
36
|
+
* their own providers via `registerAttributeProvider()`.
|
|
37
|
+
*/
|
|
38
|
+
registry = new AttributeProviderRegistry();
|
|
39
|
+
constructor(options = {}) {
|
|
40
|
+
if (options.mode)
|
|
41
|
+
this.mode = options.mode;
|
|
42
|
+
if (options.usageReporter)
|
|
43
|
+
this.usageReporter = options.usageReporter;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Register an `AttributeProvider`. Idempotent on `provider.name` —
|
|
47
|
+
* re-registering with the same name replaces the previous instance.
|
|
48
|
+
* Provider attributes flow into every `flag()` eval automatically.
|
|
49
|
+
* Dev-supplied attrs (via `setContext` / per-call `context`) win on
|
|
50
|
+
* collision (locked decision #20).
|
|
51
|
+
*/
|
|
52
|
+
registerAttributeProvider(provider) {
|
|
53
|
+
this.registry.register(provider);
|
|
54
|
+
}
|
|
55
|
+
/** Remove a previously-registered provider by name. No-op if not present. */
|
|
56
|
+
unregisterAttributeProvider(name) {
|
|
57
|
+
this.registry.unregister(name);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Expose the registry for advanced callers (e.g. async `applyTo()` refreshes
|
|
61
|
+
* driven by framework auth events). Most consumers should prefer
|
|
62
|
+
* `registerAttributeProvider` / `unregisterAttributeProvider`.
|
|
63
|
+
*/
|
|
64
|
+
getAttributeProviderRegistry() {
|
|
65
|
+
return this.registry;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Wire a usage reporter post-construction. The flag-eval path will call
|
|
69
|
+
* `reporter.report('bridge.flag_evaluations', 1)` on every successful eval
|
|
70
|
+
* (i.e. when a cached flag is present and evaluated). Discovery-only paths
|
|
71
|
+
* — first-sight unknown flag → default — do NOT count.
|
|
72
|
+
*/
|
|
73
|
+
setUsageReporter(reporter) {
|
|
74
|
+
this.usageReporter = reporter;
|
|
75
|
+
}
|
|
76
|
+
/** Read the active runtime mode. */
|
|
77
|
+
getMode() {
|
|
78
|
+
return this.mode;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Set a stable server-instance identity (TBP-172). When set, backend flags
|
|
82
|
+
* that explicitly opt into system-level targeting can bucket on this value
|
|
83
|
+
* (e.g. canary a feature to one specific instance). Most evals continue to
|
|
84
|
+
* use the per-call/per-context identity.
|
|
85
|
+
*/
|
|
86
|
+
setServerInstanceId(id) {
|
|
87
|
+
if (typeof id !== 'string' || id.length === 0)
|
|
88
|
+
return;
|
|
89
|
+
this.serverInstanceIdValue = id;
|
|
90
|
+
}
|
|
91
|
+
/** Read the configured server-instance id, or undefined when not set. */
|
|
92
|
+
getServerInstanceId() {
|
|
93
|
+
return this.serverInstanceIdValue;
|
|
94
|
+
}
|
|
95
|
+
/** Replace or merge the eval context. */
|
|
96
|
+
setContext(ctx, merge = false) {
|
|
97
|
+
if (merge) {
|
|
98
|
+
this.context = {
|
|
99
|
+
identity: ctx.identity ?? this.context.identity,
|
|
100
|
+
attributes: { ...this.context.attributes, ...ctx.attributes },
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
this.context = ctx;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/** Return a defensive shallow copy of the current eval context. */
|
|
108
|
+
getContext() {
|
|
109
|
+
return { identity: this.context.identity, attributes: { ...this.context.attributes } };
|
|
110
|
+
}
|
|
111
|
+
/** Replace the cache from a bulk hydrate (e.g. response from bridge-api). */
|
|
112
|
+
hydrate(flags) {
|
|
113
|
+
this.cache.clear();
|
|
114
|
+
for (const f of flags) {
|
|
115
|
+
this.cache.set(f.key, f);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/** Replace or insert a single flag (used by live updates). */
|
|
119
|
+
upsert(flag) {
|
|
120
|
+
this.cache.set(flag.key, flag);
|
|
121
|
+
}
|
|
122
|
+
/** Remove a flag from the cache. */
|
|
123
|
+
remove(key) {
|
|
124
|
+
this.cache.delete(key);
|
|
125
|
+
}
|
|
126
|
+
/** Register telemetry hooks. Replaces any previous hooks. */
|
|
127
|
+
setHooks(hooks) {
|
|
128
|
+
this.hooks = hooks;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Read a flag value. Returns `defaultValue` when the flag isn't known yet.
|
|
132
|
+
* TypeScript infers `T` from `defaultValue`, so callers don't write casts.
|
|
133
|
+
*
|
|
134
|
+
* An optional per-call `context` overrides the SDK's global context for
|
|
135
|
+
* just this eval. Attributes deep-merge — per-call wins on overlap, global
|
|
136
|
+
* keys not in the override are preserved.
|
|
137
|
+
*/
|
|
138
|
+
flag(key, defaultValue, context) {
|
|
139
|
+
const cached = this.cache.get(key);
|
|
140
|
+
const now = Date.now();
|
|
141
|
+
const observedType = inferType(defaultValue);
|
|
142
|
+
// Phase 1 / US-13 — merge AttributeProvider-supplied attrs into the eval
|
|
143
|
+
// context on every call. Precedence (locked decision #20):
|
|
144
|
+
// providers (lowest) < setContext globals < per-call context (highest)
|
|
145
|
+
// Sync-only here: `collectSync()` skips any async provider for this eval
|
|
146
|
+
// (those refresh via `applyTo()` on auth/billing change events).
|
|
147
|
+
const providerAttrs = this.registry.size() > 0 ? this.registry.collectSync() : undefined;
|
|
148
|
+
let effectiveCtx;
|
|
149
|
+
if (!context && !providerAttrs) {
|
|
150
|
+
effectiveCtx = this.context;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
effectiveCtx = {
|
|
154
|
+
identity: context?.identity ?? this.context.identity,
|
|
155
|
+
attributes: {
|
|
156
|
+
...(providerAttrs ?? {}),
|
|
157
|
+
...this.context.attributes,
|
|
158
|
+
...(context?.attributes ?? {}),
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
// Observe per-call attribute keys so the admin UI's attribute catalog
|
|
163
|
+
// surfaces what dev code actually supplies (powers TBP-178 collision
|
|
164
|
+
// detection + custom attribute autocomplete). Dedup per (key, value) in
|
|
165
|
+
// this runtime to keep the batcher quiet.
|
|
166
|
+
if (context?.attributes) {
|
|
167
|
+
for (const [attrKey, attrVal] of Object.entries(context.attributes)) {
|
|
168
|
+
if (!attrKey)
|
|
169
|
+
continue;
|
|
170
|
+
const dedupKey = `${attrKey}::${canonicalSampleKey(attrVal)}`;
|
|
171
|
+
if (this.observedAttributeKeys.has(dedupKey))
|
|
172
|
+
continue;
|
|
173
|
+
this.observedAttributeKeys.add(dedupKey);
|
|
174
|
+
this.safeHook(() => this.hooks.onAttributeObserved?.({
|
|
175
|
+
key: attrKey,
|
|
176
|
+
sampleValue: attrVal,
|
|
177
|
+
observedType: inferType(attrVal),
|
|
178
|
+
timestamp: now,
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Backend mode (TBP-170): refuse to evaluate user-level rules without an
|
|
183
|
+
// identity. Returns the developer's `defaultValue` rather than guessing
|
|
184
|
+
// with anonymous bucketing. Warn once per flag per runtime.
|
|
185
|
+
if (this.mode === 'backend' && !effectiveCtx.identity && cached?.state === 'on-with-rule') {
|
|
186
|
+
if (!this.missingIdentityWarned.has(key)) {
|
|
187
|
+
this.missingIdentityWarned.add(key);
|
|
188
|
+
try {
|
|
189
|
+
// eslint-disable-next-line no-console
|
|
190
|
+
globalThis.console?.warn?.(`[bridge.flag] '${key}': backend eval requires an explicit identity; returning default. ` +
|
|
191
|
+
`Pass context.identity per call, or use a server-instance id for system-level flags.`);
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
// ignore console errors
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return { passed: false, value: defaultValue };
|
|
198
|
+
}
|
|
199
|
+
if (!cached) {
|
|
200
|
+
// First sight — emit a discovery event so the server creates the
|
|
201
|
+
// record. Dedupe per (key) in this runtime; server is the authority.
|
|
202
|
+
if (!this.discoveredKeys.has(key)) {
|
|
203
|
+
this.discoveredKeys.add(key);
|
|
204
|
+
this.safeHook(() => this.hooks.onDiscover?.({
|
|
205
|
+
flag: key,
|
|
206
|
+
defaultValue,
|
|
207
|
+
observedType,
|
|
208
|
+
timestamp: now,
|
|
209
|
+
}));
|
|
210
|
+
}
|
|
211
|
+
return { passed: false, value: defaultValue };
|
|
212
|
+
}
|
|
213
|
+
const result = this.evaluateCached(cached, effectiveCtx);
|
|
214
|
+
const value = result.value === undefined ? defaultValue : result.value;
|
|
215
|
+
this.safeHook(() => this.hooks.onEval?.({
|
|
216
|
+
flag: key,
|
|
217
|
+
value,
|
|
218
|
+
variantIndex: result.variantIndex,
|
|
219
|
+
identity: effectiveCtx.identity,
|
|
220
|
+
timestamp: now,
|
|
221
|
+
}));
|
|
222
|
+
// Billing 2.0 US-10 (TBP-262): SDK-side flag_evaluations self-report.
|
|
223
|
+
// Fire-and-forget; the reporter handles batching + errors. One call per
|
|
224
|
+
// eval — there's no batched flag API, so no multiplier needed.
|
|
225
|
+
if (this.usageReporter) {
|
|
226
|
+
this.safeHook(() => this.usageReporter?.report('bridge.flag_evaluations', 1));
|
|
227
|
+
}
|
|
228
|
+
// Fail-safe type check: if the cached value doesn't match the dev's
|
|
229
|
+
// declared default type, fall back to the default. Protects the app
|
|
230
|
+
// from admin-side type mistakes (TBP-159 validation should catch most
|
|
231
|
+
// of these at save time; this is the last-mile safety net).
|
|
232
|
+
if (!typeMatches(value, observedType)) {
|
|
233
|
+
return { passed: false, value: defaultValue };
|
|
234
|
+
}
|
|
235
|
+
return { passed: result.matched, value };
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Internal — evaluate the cached flag against an eval context.
|
|
239
|
+
*/
|
|
240
|
+
evaluateCached(cached, ctx) {
|
|
241
|
+
switch (cached.state) {
|
|
242
|
+
case 'off':
|
|
243
|
+
return { value: cached.offValue, variantIndex: -1, matched: false, excludedByRollout: false };
|
|
244
|
+
case 'on':
|
|
245
|
+
return { value: cached.onValue, variantIndex: 0, matched: true, excludedByRollout: false };
|
|
246
|
+
case 'on-with-rule': {
|
|
247
|
+
if (!cached.rule) {
|
|
248
|
+
// Defensive: state says on-with-rule but no rule. Fall back to on.
|
|
249
|
+
return { value: cached.onValue, variantIndex: -1, matched: false, excludedByRollout: false };
|
|
250
|
+
}
|
|
251
|
+
return evaluateRule(cached.rule, cached.key, ctx);
|
|
252
|
+
}
|
|
253
|
+
default:
|
|
254
|
+
return { value: cached.offValue, variantIndex: -1, matched: false, excludedByRollout: false };
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/** Number of cached flags. Useful for debugging + tests. */
|
|
258
|
+
cacheSize() {
|
|
259
|
+
return this.cache.size;
|
|
260
|
+
}
|
|
261
|
+
/** Get a snapshot of cached flag keys. */
|
|
262
|
+
cachedKeys() {
|
|
263
|
+
return Array.from(this.cache.keys());
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* @deprecated Per-call observations now power the admin attribute catalog
|
|
267
|
+
* automatically — just pass attributes when you evaluate a flag:
|
|
268
|
+
* `bridge.flag('feat', false, { attributes: { plan: 'pro' } })`.
|
|
269
|
+
* The SDK reports each `(key, sampleValue)` once via `onAttributeObserved`,
|
|
270
|
+
* which the batcher relays to `/v1/flags/discover` with `kind: 'attribute'`.
|
|
271
|
+
* `declareAttributes()` will be removed in a future minor release.
|
|
272
|
+
*/
|
|
273
|
+
declareAttributes(declarations) {
|
|
274
|
+
const now = Date.now();
|
|
275
|
+
for (const [name, type] of Object.entries(declarations)) {
|
|
276
|
+
if (typeof name !== 'string' || name.length === 0)
|
|
277
|
+
continue;
|
|
278
|
+
if (this.attributeDeclarations.get(name) === type)
|
|
279
|
+
continue; // same as before; no-op
|
|
280
|
+
this.attributeDeclarations.set(name, type);
|
|
281
|
+
this.safeHook(() => this.hooks.onAttributeDeclaration?.({ name, type, timestamp: now }));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/** Read the current attribute type declarations. Useful for tests + framework wrappers. */
|
|
285
|
+
getAttributeDeclarations() {
|
|
286
|
+
return Object.fromEntries(this.attributeDeclarations.entries());
|
|
287
|
+
}
|
|
288
|
+
safeHook(fn) {
|
|
289
|
+
try {
|
|
290
|
+
fn();
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
// Telemetry must never break eval. Silently swallow.
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// ── Type inference helpers ──────────────────────────────────────────────────
|
|
298
|
+
function inferType(v) {
|
|
299
|
+
if (typeof v === 'boolean')
|
|
300
|
+
return 'boolean';
|
|
301
|
+
if (typeof v === 'number')
|
|
302
|
+
return 'number';
|
|
303
|
+
if (typeof v === 'string')
|
|
304
|
+
return 'string';
|
|
305
|
+
return 'json';
|
|
306
|
+
}
|
|
307
|
+
/** Stable string key for an attribute sample value — used for in-process dedup
|
|
308
|
+
* in `observedAttributeKeys`. Safe for primitives + JSON-serialisable values. */
|
|
309
|
+
function canonicalSampleKey(v) {
|
|
310
|
+
if (v === undefined)
|
|
311
|
+
return '∅undef';
|
|
312
|
+
if (v === null)
|
|
313
|
+
return '∅null';
|
|
314
|
+
if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean')
|
|
315
|
+
return String(v);
|
|
316
|
+
try {
|
|
317
|
+
return JSON.stringify(v);
|
|
318
|
+
}
|
|
319
|
+
catch {
|
|
320
|
+
return '∅unserialisable';
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
function typeMatches(v, expected) {
|
|
324
|
+
if (v === undefined || v === null)
|
|
325
|
+
return false;
|
|
326
|
+
switch (expected) {
|
|
327
|
+
case 'boolean':
|
|
328
|
+
return typeof v === 'boolean';
|
|
329
|
+
case 'number':
|
|
330
|
+
return typeof v === 'number';
|
|
331
|
+
case 'string':
|
|
332
|
+
return typeof v === 'string';
|
|
333
|
+
case 'json':
|
|
334
|
+
return true;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
//# sourceMappingURL=flag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flag.js","sourceRoot":"","sources":["../../src/flags/flag.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { BridgeFlags } from './flag.js';
|
|
2
|
+
/** How aggressively the anon ID is persisted. */
|
|
3
|
+
export type AnonymousTrackingMode = 'persistent' | 'session' | 'none';
|
|
4
|
+
/**
|
|
5
|
+
* Pluggable storage for the anonymous identity. Framework SDKs implement
|
|
6
|
+
* this against the right platform API.
|
|
7
|
+
*/
|
|
8
|
+
export interface IdentityStorage {
|
|
9
|
+
/** Persistence flavor — informational only; storage choice itself enforces it. */
|
|
10
|
+
readonly mode: AnonymousTrackingMode;
|
|
11
|
+
/** Read the stored anon ID, or undefined if not set. */
|
|
12
|
+
read(): string | undefined;
|
|
13
|
+
/** Write the anon ID. */
|
|
14
|
+
write(id: string): void;
|
|
15
|
+
/** Drop the anon ID (e.g. on logout). */
|
|
16
|
+
clear(): void;
|
|
17
|
+
}
|
|
18
|
+
/** In-memory storage. Used for SSR, tests, or when `tracking: 'none'`. */
|
|
19
|
+
export declare class MemoryIdentityStorage implements IdentityStorage {
|
|
20
|
+
readonly mode: AnonymousTrackingMode;
|
|
21
|
+
private value;
|
|
22
|
+
constructor(mode?: AnonymousTrackingMode);
|
|
23
|
+
read(): string | undefined;
|
|
24
|
+
write(id: string): void;
|
|
25
|
+
clear(): void;
|
|
26
|
+
}
|
|
27
|
+
/** RFC4122-shaped UUID v4. Uses `crypto.randomUUID` when available, falls back to Math.random. */
|
|
28
|
+
export declare function generateAnonymousId(): string;
|
|
29
|
+
/**
|
|
30
|
+
* Identity manager bundled with a `BridgeFlags` instance. Created via the
|
|
31
|
+
* factory below — framework SDKs call `attachIdentity(bridge, storage)`
|
|
32
|
+
* during bootstrap so anonymous ID auto-populates the eval context.
|
|
33
|
+
*/
|
|
34
|
+
export declare class BridgeIdentity {
|
|
35
|
+
private readonly bridge;
|
|
36
|
+
private readonly storage;
|
|
37
|
+
/** Fires when the identity transitions from anonymous → known (TBP-169). */
|
|
38
|
+
private onIdentifyHook?;
|
|
39
|
+
/** True once `identify()` has been called (or a non-anonymous identity was loaded). */
|
|
40
|
+
private knownUserId?;
|
|
41
|
+
constructor(bridge: BridgeFlags, storage: IdentityStorage);
|
|
42
|
+
/** Read the current anonymous ID, generating + persisting on first call. */
|
|
43
|
+
ensureAnonymousId(): string;
|
|
44
|
+
/**
|
|
45
|
+
* Push the anonymous ID into the BridgeFlags global eval context. Idempotent.
|
|
46
|
+
* No-op if a known userId is already set.
|
|
47
|
+
*/
|
|
48
|
+
hydrateAnonymous(): string;
|
|
49
|
+
/**
|
|
50
|
+
* Promote the SDK from anonymous to known. Updates the global identity in
|
|
51
|
+
* `BridgeFlags` and fires the `onIdentify` hook so the server can link
|
|
52
|
+
* anon-id telemetry to the known user's history.
|
|
53
|
+
*/
|
|
54
|
+
identify(userId: string): void;
|
|
55
|
+
/**
|
|
56
|
+
* Drop the known identity and revert to anonymous. Used on logout. The
|
|
57
|
+
* anonymous ID itself is preserved unless `dropAnonymous` is also passed.
|
|
58
|
+
*/
|
|
59
|
+
logout(options?: {
|
|
60
|
+
dropAnonymous?: boolean;
|
|
61
|
+
}): void;
|
|
62
|
+
/** Register a one-time hook fired on identify(). Used by the SDK telemetry batcher. */
|
|
63
|
+
setOnIdentify(hook: (args: {
|
|
64
|
+
anonymousId?: string;
|
|
65
|
+
userId: string;
|
|
66
|
+
}) => void): void;
|
|
67
|
+
/** True when `identify()` has set a known user. */
|
|
68
|
+
isKnown(): boolean;
|
|
69
|
+
/** Read the current effective identity (known userId or anonymous ID). */
|
|
70
|
+
current(): string | undefined;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Factory: attach an anonymous-aware identity manager to a `BridgeFlags`
|
|
74
|
+
* instance. Pass a storage implementation appropriate for the platform.
|
|
75
|
+
*/
|
|
76
|
+
export declare function attachIdentity(bridge: BridgeFlags, storage: IdentityStorage): BridgeIdentity;
|
|
77
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/flags/identity.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,iDAAiD;AACjD,MAAM,MAAM,qBAAqB,GAAG,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;AAEtE;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,kFAAkF;IAClF,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,wDAAwD;IACxD,IAAI,IAAI,MAAM,GAAG,SAAS,CAAC;IAC3B,yBAAyB;IACzB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,yCAAyC;IACzC,KAAK,IAAI,IAAI,CAAC;CACf;AAED,0EAA0E;AAC1E,qBAAa,qBAAsB,YAAW,eAAe;IAC3D,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,OAAO,CAAC,KAAK,CAAqB;gBAEtB,IAAI,GAAE,qBAA8B;IAIhD,IAAI,IAAI,MAAM,GAAG,SAAS;IAG1B,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAGvB,KAAK,IAAI,IAAI;CAGd;AAED,kGAAkG;AAClG,wBAAgB,mBAAmB,IAAI,MAAM,CAS5C;AAED;;;;GAIG;AACH,qBAAa,cAAc;IAOvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAP1B,4EAA4E;IAC5E,OAAO,CAAC,cAAc,CAAC,CAA2D;IAClF,uFAAuF;IACvF,OAAO,CAAC,WAAW,CAAC,CAAS;gBAGV,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,eAAe;IAG3C,4EAA4E;IAC5E,iBAAiB,IAAI,MAAM;IAQ3B;;;OAGG;IACH,gBAAgB,IAAI,MAAM;IAO1B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAc9B;;;OAGG;IACH,MAAM,CAAC,OAAO,GAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,IAAI;IAMvD,uFAAuF;IACvF,aAAa,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,IAAI;IAInF,mDAAmD;IACnD,OAAO,IAAI,OAAO;IAIlB,0EAA0E;IAC1E,OAAO,IAAI,MAAM,GAAG,SAAS;CAI9B;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,GAAG,cAAc,CAK5F"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// Anonymous identity + `identify` for Bridge Feature Flags (TBP-168, TBP-169).
|
|
2
|
+
//
|
|
3
|
+
// Frontends usually want a stable anonymous identifier for users who haven't
|
|
4
|
+
// logged in, so flag evaluation has *something* to bucket on (especially for
|
|
5
|
+
// percentage rollouts). This module:
|
|
6
|
+
//
|
|
7
|
+
// 1. Defines a pluggable IdentityStorage interface so framework SDKs can
|
|
8
|
+
// back it with localStorage / sessionStorage / cookies / memory.
|
|
9
|
+
// 2. Generates a UUID v4 on first init and persists it.
|
|
10
|
+
// 3. Provides `identify(userId)` to upgrade the anon → known state.
|
|
11
|
+
//
|
|
12
|
+
// auth-core itself is platform-agnostic; the framework SDKs (bridge-svelte,
|
|
13
|
+
// bridge-react, bridge-nextjs) supply the browser-storage implementations.
|
|
14
|
+
// auth-core ships `MemoryIdentityStorage` for tests / SSR.
|
|
15
|
+
/** In-memory storage. Used for SSR, tests, or when `tracking: 'none'`. */
|
|
16
|
+
export class MemoryIdentityStorage {
|
|
17
|
+
mode;
|
|
18
|
+
value;
|
|
19
|
+
constructor(mode = 'none') {
|
|
20
|
+
this.mode = mode;
|
|
21
|
+
}
|
|
22
|
+
read() {
|
|
23
|
+
return this.value;
|
|
24
|
+
}
|
|
25
|
+
write(id) {
|
|
26
|
+
this.value = id;
|
|
27
|
+
}
|
|
28
|
+
clear() {
|
|
29
|
+
this.value = undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** RFC4122-shaped UUID v4. Uses `crypto.randomUUID` when available, falls back to Math.random. */
|
|
33
|
+
export function generateAnonymousId() {
|
|
34
|
+
// Prefer Web Crypto / Node 20+ crypto.randomUUID
|
|
35
|
+
const g = globalThis;
|
|
36
|
+
if (g.crypto && typeof g.crypto.randomUUID === 'function') {
|
|
37
|
+
return `anon_${g.crypto.randomUUID()}`;
|
|
38
|
+
}
|
|
39
|
+
// Fallback: Math.random-based v4 (acceptable for anon IDs — they're not security tokens)
|
|
40
|
+
const hex = (n) => Math.floor(Math.random() * (1 << (n * 4))).toString(16).padStart(n, '0');
|
|
41
|
+
return `anon_${hex(8)}-${hex(4)}-4${hex(3)}-${(8 + Math.floor(Math.random() * 4)).toString(16)}${hex(3)}-${hex(12)}`;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Identity manager bundled with a `BridgeFlags` instance. Created via the
|
|
45
|
+
* factory below — framework SDKs call `attachIdentity(bridge, storage)`
|
|
46
|
+
* during bootstrap so anonymous ID auto-populates the eval context.
|
|
47
|
+
*/
|
|
48
|
+
export class BridgeIdentity {
|
|
49
|
+
bridge;
|
|
50
|
+
storage;
|
|
51
|
+
/** Fires when the identity transitions from anonymous → known (TBP-169). */
|
|
52
|
+
onIdentifyHook;
|
|
53
|
+
/** True once `identify()` has been called (or a non-anonymous identity was loaded). */
|
|
54
|
+
knownUserId;
|
|
55
|
+
constructor(bridge, storage) {
|
|
56
|
+
this.bridge = bridge;
|
|
57
|
+
this.storage = storage;
|
|
58
|
+
}
|
|
59
|
+
/** Read the current anonymous ID, generating + persisting on first call. */
|
|
60
|
+
ensureAnonymousId() {
|
|
61
|
+
const existing = this.storage.read();
|
|
62
|
+
if (existing)
|
|
63
|
+
return existing;
|
|
64
|
+
const fresh = generateAnonymousId();
|
|
65
|
+
this.storage.write(fresh);
|
|
66
|
+
return fresh;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Push the anonymous ID into the BridgeFlags global eval context. Idempotent.
|
|
70
|
+
* No-op if a known userId is already set.
|
|
71
|
+
*/
|
|
72
|
+
hydrateAnonymous() {
|
|
73
|
+
if (this.knownUserId)
|
|
74
|
+
return this.knownUserId;
|
|
75
|
+
const anonId = this.ensureAnonymousId();
|
|
76
|
+
this.bridge.setContext({ identity: anonId, attributes: {} }, true);
|
|
77
|
+
return anonId;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Promote the SDK from anonymous to known. Updates the global identity in
|
|
81
|
+
* `BridgeFlags` and fires the `onIdentify` hook so the server can link
|
|
82
|
+
* anon-id telemetry to the known user's history.
|
|
83
|
+
*/
|
|
84
|
+
identify(userId) {
|
|
85
|
+
if (!userId)
|
|
86
|
+
throw new Error('identify(userId): userId must be a non-empty string');
|
|
87
|
+
const previousAnon = this.knownUserId ? undefined : this.storage.read();
|
|
88
|
+
this.knownUserId = userId;
|
|
89
|
+
this.bridge.setContext({ identity: userId, attributes: {} }, true);
|
|
90
|
+
if (this.onIdentifyHook) {
|
|
91
|
+
try {
|
|
92
|
+
this.onIdentifyHook({ anonymousId: previousAnon, userId });
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Hook errors must not break identify().
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Drop the known identity and revert to anonymous. Used on logout. The
|
|
101
|
+
* anonymous ID itself is preserved unless `dropAnonymous` is also passed.
|
|
102
|
+
*/
|
|
103
|
+
logout(options = {}) {
|
|
104
|
+
this.knownUserId = undefined;
|
|
105
|
+
if (options.dropAnonymous)
|
|
106
|
+
this.storage.clear();
|
|
107
|
+
this.hydrateAnonymous();
|
|
108
|
+
}
|
|
109
|
+
/** Register a one-time hook fired on identify(). Used by the SDK telemetry batcher. */
|
|
110
|
+
setOnIdentify(hook) {
|
|
111
|
+
this.onIdentifyHook = hook;
|
|
112
|
+
}
|
|
113
|
+
/** True when `identify()` has set a known user. */
|
|
114
|
+
isKnown() {
|
|
115
|
+
return !!this.knownUserId;
|
|
116
|
+
}
|
|
117
|
+
/** Read the current effective identity (known userId or anonymous ID). */
|
|
118
|
+
current() {
|
|
119
|
+
if (this.knownUserId)
|
|
120
|
+
return this.knownUserId;
|
|
121
|
+
return this.storage.read();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Factory: attach an anonymous-aware identity manager to a `BridgeFlags`
|
|
126
|
+
* instance. Pass a storage implementation appropriate for the platform.
|
|
127
|
+
*/
|
|
128
|
+
export function attachIdentity(bridge, storage) {
|
|
129
|
+
const identity = new BridgeIdentity(bridge, storage);
|
|
130
|
+
// Eagerly populate context.identity so anonymous evals work from boot.
|
|
131
|
+
identity.hydrateAnonymous();
|
|
132
|
+
return identity;
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/flags/identity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export { OPERATORS, OPERATOR_VERSION, CONDITIONS_PER_RULE_MAX, isOperator, isOperatorValidForType, validOperatorsForType, evaluateCondition, validateConditions, } from './operators.js';
|
|
2
|
+
export type { Operator, AttributeType, Condition, ConditionValue, ValidationError, } from './operators.js';
|
|
3
|
+
export { bucket, evaluateBranch, evaluateRule, resolveAttribute, validateRule, } from './evaluator.js';
|
|
4
|
+
export type { Branch, Rule, FlagState, EvalContext, EvalResult, RuleValidationError, } from './evaluator.js';
|
|
5
|
+
export { BridgeFlags } from './flag.js';
|
|
6
|
+
export type { CachedFlag, FlagEvalResult, FlagValueType, EvalTelemetry, DiscoveryTelemetry, BridgeFlagsHooks, DeclaredAttributeType, AttributeDeclaration, BridgeFlagsMode, FlagUsageReporterLike, } from './flag.js';
|
|
7
|
+
export { BridgeIdentity, MemoryIdentityStorage, attachIdentity, generateAnonymousId, } from './identity.js';
|
|
8
|
+
export type { AnonymousTrackingMode, IdentityStorage, } from './identity.js';
|
|
9
|
+
export { AttributeProviderRegistry, AuthAttributeProvider, BillingAttributeProvider, } from './attribute-providers.js';
|
|
10
|
+
export type { AttributeProvider, AuthJwtClaims, AuthProviderConfig, BillingSnapshot, BillingProviderConfig, BillingProviderStores, } from './attribute-providers.js';
|
|
11
|
+
export { DevAttributeProvider } from './dev-attribute-provider.js';
|
|
12
|
+
export type { AttributeGetter, AttributeBulkGetter, SetOptions as AttributesSetOptions, } from './dev-attribute-provider.js';
|
|
13
|
+
export { BridgePullCache } from './runtime-mode.js';
|
|
14
|
+
export type { BridgeRuntimeMode, PullCacheOptions } from './runtime-mode.js';
|
|
15
|
+
export { TelemetryBatcher } from './telemetry.js';
|
|
16
|
+
export type { TelemetryBatcherConfig } from './telemetry.js';
|
|
17
|
+
export { RealtimeClient } from './realtime.js';
|
|
18
|
+
export type { RealtimeClientConfig, RealtimeMessage, FlagUpdateMessage, FlagRemovedMessage, UserStateMessage, SubscriptionPlanChangedMessage, BillingLifecycleMessage, QuotaUpdatedMessage, EntitlementsChangedMessage, SessionSnapshotMessage, ConnectionState, WebSocketLike, } from './realtime.js';
|
|
19
|
+
export { BRIDGE_CONTEXT_HEADER, serializeContext, deserializeContext, serverInstanceId, } from './propagation.js';
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/flags/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,uBAAuB,EACvB,UAAU,EACV,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACV,QAAQ,EACR,aAAa,EACb,SAAS,EACT,cAAc,EACd,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,MAAM,EACN,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,YAAY,GACb,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACV,MAAM,EACN,IAAI,EACJ,SAAS,EACT,WAAW,EACX,UAAU,EACV,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,YAAY,EACV,UAAU,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,eAAe,EACf,qBAAqB,GACtB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,qBAAqB,EACrB,eAAe,GAChB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAIlC,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,UAAU,IAAI,oBAAoB,GACnC,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,YAAY,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAG7D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EACV,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,8BAA8B,EAC9B,uBAAuB,EACvB,mBAAmB,EACnB,0BAA0B,EAC1B,sBAAsB,EACtB,eAAe,EACf,aAAa,GACd,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export { OPERATORS, OPERATOR_VERSION, CONDITIONS_PER_RULE_MAX, isOperator, isOperatorValidForType, validOperatorsForType, evaluateCondition, validateConditions, } from './operators.js';
|
|
2
|
+
// Rule + branches + evaluator (TBP-160, TBP-158)
|
|
3
|
+
export { bucket, evaluateBranch, evaluateRule, resolveAttribute, validateRule, } from './evaluator.js';
|
|
4
|
+
// SDK API: bridge.flag(key, default) with type inference (TBP-160)
|
|
5
|
+
export { BridgeFlags } from './flag.js';
|
|
6
|
+
// Identity: anonymous ID + `identify` (TBP-168, TBP-169)
|
|
7
|
+
export { BridgeIdentity, MemoryIdentityStorage, attachIdentity, generateAnonymousId, } from './identity.js';
|
|
8
|
+
// AttributeProvider plugin model (TBP-173)
|
|
9
|
+
export { AttributeProviderRegistry, AuthAttributeProvider, BillingAttributeProvider, } from './attribute-providers.js';
|
|
10
|
+
// Phase 5 (TBP-328/329/330) — dev-managed AttributeProvider backing the
|
|
11
|
+
// `bridge.attributes` write surface in framework SDKs.
|
|
12
|
+
export { DevAttributeProvider } from './dev-attribute-provider.js';
|
|
13
|
+
// Phase 6 (TBP-290/340) — runtime mode + pull-mode cache for backend SDKs.
|
|
14
|
+
export { BridgePullCache } from './runtime-mode.js';
|
|
15
|
+
// SDK telemetry batcher (TBP-157)
|
|
16
|
+
export { TelemetryBatcher } from './telemetry.js';
|
|
17
|
+
// SDK realtime client (TBP-150)
|
|
18
|
+
export { RealtimeClient } from './realtime.js';
|
|
19
|
+
// FE → BE context propagation (TBP-171) + server-instance ID (TBP-172)
|
|
20
|
+
export { BRIDGE_CONTEXT_HEADER, serializeContext, deserializeContext, serverInstanceId, } from './propagation.js';
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/flags/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,uBAAuB,EACvB,UAAU,EACV,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AAUxB,iDAAiD;AACjD,OAAO,EACL,MAAM,EACN,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,YAAY,GACb,MAAM,gBAAgB,CAAC;AAWxB,mEAAmE;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAcxC,yDAAyD;AACzD,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,mBAAmB,GACpB,MAAM,eAAe,CAAC;AAMvB,2CAA2C;AAC3C,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAUlC,wEAAwE;AACxE,uDAAuD;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAOnE,2EAA2E;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD,kCAAkC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGlD,gCAAgC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAgB/C,uEAAuE;AACvE,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,kBAAkB,CAAC"}
|