@nebulr-group/bridge-auth-core 0.1.2 → 0.4.0-beta.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.
- 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 +39 -1
- package/dist/bridge-auth.d.ts.map +1 -1
- package/dist/bridge-auth.js +89 -6
- 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 +353 -0
- package/dist/flags/realtime.d.ts.map +1 -0
- package/dist/flags/realtime.js +779 -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 +4 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +44 -12
- 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,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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export declare const OPERATORS: readonly ["eq", "neq", "contains", "not_contains", "in", "not_in", "gt", "lt", "between", "regex", "exists", "not_exists"];
|
|
2
|
+
export type Operator = (typeof OPERATORS)[number];
|
|
3
|
+
export declare const OPERATOR_VERSION: 1;
|
|
4
|
+
export type AttributeType = 'string' | 'number' | 'boolean' | 'date';
|
|
5
|
+
export declare function isOperator(value: unknown): value is Operator;
|
|
6
|
+
export declare function isOperatorValidForType(op: Operator, type: AttributeType): boolean;
|
|
7
|
+
export declare function validOperatorsForType(type: AttributeType): ReadonlyArray<Operator>;
|
|
8
|
+
export declare const CONDITIONS_PER_RULE_MAX = 50;
|
|
9
|
+
export type ConditionValue = string | number | boolean | null;
|
|
10
|
+
export interface Condition {
|
|
11
|
+
attribute: string;
|
|
12
|
+
operator: Operator;
|
|
13
|
+
values: ReadonlyArray<ConditionValue>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Evaluate a single condition against an attribute value.
|
|
17
|
+
*
|
|
18
|
+
* @param condition The condition (attribute, operator, values) from the rule.
|
|
19
|
+
* @param attributeValue The value of the named attribute in the eval context.
|
|
20
|
+
* May be undefined / null if the SDK didn't supply it.
|
|
21
|
+
* @returns true if the condition matches; false otherwise.
|
|
22
|
+
*
|
|
23
|
+
* Operator semantics:
|
|
24
|
+
* eq attributeValue === values[0]
|
|
25
|
+
* neq attributeValue !== values[0]
|
|
26
|
+
* contains String(attributeValue).includes(String(values[0]))
|
|
27
|
+
* not_contains ! contains
|
|
28
|
+
* in values.includes(attributeValue)
|
|
29
|
+
* not_in ! in
|
|
30
|
+
* gt Number(attributeValue) > Number(values[0])
|
|
31
|
+
* lt Number(attributeValue) < Number(values[0])
|
|
32
|
+
* between Number(values[0]) <= Number(attributeValue) <= Number(values[1])
|
|
33
|
+
* (values[0] and values[1] are auto-swapped if out of order)
|
|
34
|
+
* regex new RegExp(String(values[0])).test(String(attributeValue))
|
|
35
|
+
* exists attributeValue !== undefined && attributeValue !== null
|
|
36
|
+
* not_exists ! exists
|
|
37
|
+
*
|
|
38
|
+
* Fail-safe rule: any malformed input (wrong number of values, non-numeric
|
|
39
|
+
* value for a numeric operator, invalid regex, oversized input) returns false
|
|
40
|
+
* rather than throwing. The server must still validate at save time; this
|
|
41
|
+
* function is intentionally lenient at runtime so a bad rule never crashes
|
|
42
|
+
* the consuming app.
|
|
43
|
+
*/
|
|
44
|
+
export declare function evaluateCondition(condition: Condition, attributeValue: unknown): boolean;
|
|
45
|
+
export interface ValidationError {
|
|
46
|
+
/** Index of the condition within its containing branch (or -1 if global). */
|
|
47
|
+
conditionIndex: number;
|
|
48
|
+
attribute: string;
|
|
49
|
+
operator: Operator;
|
|
50
|
+
message: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Validate a list of conditions against a known attribute type map at save time.
|
|
54
|
+
*
|
|
55
|
+
* @param conditions The conditions to validate (e.g. a branch's `conditions`).
|
|
56
|
+
* @param attributeTypes Map of attribute key → known type. If an attribute is
|
|
57
|
+
* not in the map its type is treated as unknown and
|
|
58
|
+
* validation only checks operator membership in the
|
|
59
|
+
* locked set (not type compatibility).
|
|
60
|
+
* @returns list of validation errors; empty list means valid.
|
|
61
|
+
*/
|
|
62
|
+
export declare function validateConditions(conditions: ReadonlyArray<Condition>, attributeTypes?: Readonly<Record<string, AttributeType>>): ValidationError[];
|
|
63
|
+
//# sourceMappingURL=operators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operators.d.ts","sourceRoot":"","sources":["../../src/flags/operators.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,SAAS,4HAaZ,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAElD,eAAO,MAAM,gBAAgB,EAAG,CAAU,CAAC;AAE3C,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAarE,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAE5D;AAED,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAEjF;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,aAAa,GAAG,aAAa,CAAC,QAAQ,CAAC,CAElF;AAqBD,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAI1C,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAE9D,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;CACvC;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,GAAG,OAAO,CA4FxF;AAID,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,aAAa,CAAC,SAAS,CAAC,EACpC,cAAc,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAM,GAC3D,eAAe,EAAE,CAwGnB"}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
// The locked operator set for Bridge Feature Flags v1.
|
|
2
|
+
//
|
|
3
|
+
// This module is the SINGLE SOURCE OF TRUTH for both:
|
|
4
|
+
// - bridge-api server-side rule evaluation
|
|
5
|
+
// - bridge-* SDK client-side rule evaluation (via auth-core)
|
|
6
|
+
//
|
|
7
|
+
// Adding or removing an operator is a breaking change of the v1 contract.
|
|
8
|
+
// The `OPERATOR_VERSION` constant is forward-compat space — a stored rule
|
|
9
|
+
// carries the operator-set version it was authored against, so future
|
|
10
|
+
// expansions of the closed set can be migrated cleanly.
|
|
11
|
+
export const OPERATORS = [
|
|
12
|
+
'eq',
|
|
13
|
+
'neq',
|
|
14
|
+
'contains',
|
|
15
|
+
'not_contains',
|
|
16
|
+
'in',
|
|
17
|
+
'not_in',
|
|
18
|
+
'gt',
|
|
19
|
+
'lt',
|
|
20
|
+
'between',
|
|
21
|
+
'regex',
|
|
22
|
+
'exists',
|
|
23
|
+
'not_exists',
|
|
24
|
+
];
|
|
25
|
+
export const OPERATOR_VERSION = 1;
|
|
26
|
+
// Which operators are valid for which attribute type. Used by:
|
|
27
|
+
// - Server-side save-time validation (reject mixed-type rules)
|
|
28
|
+
// - Admin UI operator picker (filter dropdown by attribute type)
|
|
29
|
+
// - SDK eval (defensive — should already be validated server-side)
|
|
30
|
+
const VALID_OPERATORS_BY_TYPE = {
|
|
31
|
+
string: ['eq', 'neq', 'contains', 'not_contains', 'in', 'not_in', 'regex', 'exists', 'not_exists'],
|
|
32
|
+
number: ['eq', 'neq', 'gt', 'lt', 'between', 'in', 'not_in', 'exists', 'not_exists'],
|
|
33
|
+
boolean: ['eq', 'neq', 'exists', 'not_exists'],
|
|
34
|
+
date: ['eq', 'neq', 'gt', 'lt', 'between', 'exists', 'not_exists'],
|
|
35
|
+
};
|
|
36
|
+
export function isOperator(value) {
|
|
37
|
+
return typeof value === 'string' && OPERATORS.includes(value);
|
|
38
|
+
}
|
|
39
|
+
export function isOperatorValidForType(op, type) {
|
|
40
|
+
return VALID_OPERATORS_BY_TYPE[type]?.includes(op) ?? false;
|
|
41
|
+
}
|
|
42
|
+
export function validOperatorsForType(type) {
|
|
43
|
+
return VALID_OPERATORS_BY_TYPE[type] ?? [];
|
|
44
|
+
}
|
|
45
|
+
// ── Safety limits ───────────────────────────────────────────────────────────
|
|
46
|
+
//
|
|
47
|
+
// Bounds on inputs that protect against denial-of-service or pathological
|
|
48
|
+
// rules. These are deliberately generous — they exist to draw a line, not to
|
|
49
|
+
// constrain reasonable use. Anything beyond these limits is treated as a
|
|
50
|
+
// non-match rather than evaluated (fail-safe).
|
|
51
|
+
// Cap regex input length to mitigate ReDoS on malicious patterns. Inputs
|
|
52
|
+
// longer than this are treated as non-matching rather than evaluated.
|
|
53
|
+
// Note: a real sandboxed regex engine (e.g. re2-wasm) is a future hardening
|
|
54
|
+
// step. v1 caps input + uses try/catch around the standard engine.
|
|
55
|
+
const REGEX_INPUT_MAX = 10_000;
|
|
56
|
+
// Hard cap on the number of items in `in` / `not_in` value arrays.
|
|
57
|
+
const IN_LIST_MAX = 1_000;
|
|
58
|
+
// Hard cap on the number of conditions allowed in a single rule (across
|
|
59
|
+
// all branches combined). Enforced at save time by the server, exposed here
|
|
60
|
+
// so the UI can surface the limit consistently.
|
|
61
|
+
export const CONDITIONS_PER_RULE_MAX = 50;
|
|
62
|
+
// ── Evaluation ──────────────────────────────────────────────────────────────
|
|
63
|
+
/**
|
|
64
|
+
* Evaluate a single condition against an attribute value.
|
|
65
|
+
*
|
|
66
|
+
* @param condition The condition (attribute, operator, values) from the rule.
|
|
67
|
+
* @param attributeValue The value of the named attribute in the eval context.
|
|
68
|
+
* May be undefined / null if the SDK didn't supply it.
|
|
69
|
+
* @returns true if the condition matches; false otherwise.
|
|
70
|
+
*
|
|
71
|
+
* Operator semantics:
|
|
72
|
+
* eq attributeValue === values[0]
|
|
73
|
+
* neq attributeValue !== values[0]
|
|
74
|
+
* contains String(attributeValue).includes(String(values[0]))
|
|
75
|
+
* not_contains ! contains
|
|
76
|
+
* in values.includes(attributeValue)
|
|
77
|
+
* not_in ! in
|
|
78
|
+
* gt Number(attributeValue) > Number(values[0])
|
|
79
|
+
* lt Number(attributeValue) < Number(values[0])
|
|
80
|
+
* between Number(values[0]) <= Number(attributeValue) <= Number(values[1])
|
|
81
|
+
* (values[0] and values[1] are auto-swapped if out of order)
|
|
82
|
+
* regex new RegExp(String(values[0])).test(String(attributeValue))
|
|
83
|
+
* exists attributeValue !== undefined && attributeValue !== null
|
|
84
|
+
* not_exists ! exists
|
|
85
|
+
*
|
|
86
|
+
* Fail-safe rule: any malformed input (wrong number of values, non-numeric
|
|
87
|
+
* value for a numeric operator, invalid regex, oversized input) returns false
|
|
88
|
+
* rather than throwing. The server must still validate at save time; this
|
|
89
|
+
* function is intentionally lenient at runtime so a bad rule never crashes
|
|
90
|
+
* the consuming app.
|
|
91
|
+
*/
|
|
92
|
+
export function evaluateCondition(condition, attributeValue) {
|
|
93
|
+
const { operator, values } = condition;
|
|
94
|
+
// exists / not_exists handle missing values specially — short-circuit first
|
|
95
|
+
if (operator === 'exists') {
|
|
96
|
+
return attributeValue !== undefined && attributeValue !== null;
|
|
97
|
+
}
|
|
98
|
+
if (operator === 'not_exists') {
|
|
99
|
+
return attributeValue === undefined || attributeValue === null;
|
|
100
|
+
}
|
|
101
|
+
// For every other operator: a missing attribute is always a non-match
|
|
102
|
+
if (attributeValue === undefined || attributeValue === null) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
switch (operator) {
|
|
106
|
+
case 'eq':
|
|
107
|
+
return values.length > 0 && values[0] === attributeValue;
|
|
108
|
+
case 'neq':
|
|
109
|
+
return values.length > 0 && values[0] !== attributeValue;
|
|
110
|
+
case 'contains': {
|
|
111
|
+
if (values.length === 0)
|
|
112
|
+
return false;
|
|
113
|
+
return String(attributeValue).includes(String(values[0]));
|
|
114
|
+
}
|
|
115
|
+
case 'not_contains': {
|
|
116
|
+
if (values.length === 0)
|
|
117
|
+
return false;
|
|
118
|
+
return !String(attributeValue).includes(String(values[0]));
|
|
119
|
+
}
|
|
120
|
+
case 'in': {
|
|
121
|
+
if (values.length === 0 || values.length > IN_LIST_MAX)
|
|
122
|
+
return false;
|
|
123
|
+
return values.includes(attributeValue);
|
|
124
|
+
}
|
|
125
|
+
case 'not_in': {
|
|
126
|
+
// An empty `not_in` list is vacuously true (no values to exclude).
|
|
127
|
+
if (values.length > IN_LIST_MAX)
|
|
128
|
+
return false;
|
|
129
|
+
return !values.includes(attributeValue);
|
|
130
|
+
}
|
|
131
|
+
case 'gt': {
|
|
132
|
+
if (values.length === 0)
|
|
133
|
+
return false;
|
|
134
|
+
const n = Number(attributeValue);
|
|
135
|
+
const t = Number(values[0]);
|
|
136
|
+
if (Number.isNaN(n) || Number.isNaN(t))
|
|
137
|
+
return false;
|
|
138
|
+
return n > t;
|
|
139
|
+
}
|
|
140
|
+
case 'lt': {
|
|
141
|
+
if (values.length === 0)
|
|
142
|
+
return false;
|
|
143
|
+
const n = Number(attributeValue);
|
|
144
|
+
const t = Number(values[0]);
|
|
145
|
+
if (Number.isNaN(n) || Number.isNaN(t))
|
|
146
|
+
return false;
|
|
147
|
+
return n < t;
|
|
148
|
+
}
|
|
149
|
+
case 'between': {
|
|
150
|
+
if (values.length < 2)
|
|
151
|
+
return false;
|
|
152
|
+
const n = Number(attributeValue);
|
|
153
|
+
const a = Number(values[0]);
|
|
154
|
+
const b = Number(values[1]);
|
|
155
|
+
if (Number.isNaN(n) || Number.isNaN(a) || Number.isNaN(b))
|
|
156
|
+
return false;
|
|
157
|
+
const [lo, hi] = a <= b ? [a, b] : [b, a];
|
|
158
|
+
return n >= lo && n <= hi;
|
|
159
|
+
}
|
|
160
|
+
case 'regex': {
|
|
161
|
+
if (values.length === 0)
|
|
162
|
+
return false;
|
|
163
|
+
const input = String(attributeValue);
|
|
164
|
+
if (input.length > REGEX_INPUT_MAX)
|
|
165
|
+
return false;
|
|
166
|
+
try {
|
|
167
|
+
const re = new RegExp(String(values[0]));
|
|
168
|
+
return re.test(input);
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
// Invalid regex pattern — fail-safe: treat as non-match.
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
default: {
|
|
176
|
+
// Exhaustiveness check — `operator` is typed as Operator, so this
|
|
177
|
+
// branch should be unreachable. If it's hit, the rule was authored
|
|
178
|
+
// against a future operator set and we should fail-safe.
|
|
179
|
+
const _exhaustive = operator;
|
|
180
|
+
void _exhaustive;
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Validate a list of conditions against a known attribute type map at save time.
|
|
187
|
+
*
|
|
188
|
+
* @param conditions The conditions to validate (e.g. a branch's `conditions`).
|
|
189
|
+
* @param attributeTypes Map of attribute key → known type. If an attribute is
|
|
190
|
+
* not in the map its type is treated as unknown and
|
|
191
|
+
* validation only checks operator membership in the
|
|
192
|
+
* locked set (not type compatibility).
|
|
193
|
+
* @returns list of validation errors; empty list means valid.
|
|
194
|
+
*/
|
|
195
|
+
export function validateConditions(conditions, attributeTypes = {}) {
|
|
196
|
+
const errors = [];
|
|
197
|
+
conditions.forEach((c, i) => {
|
|
198
|
+
if (!isOperator(c.operator)) {
|
|
199
|
+
errors.push({
|
|
200
|
+
conditionIndex: i,
|
|
201
|
+
attribute: c.attribute,
|
|
202
|
+
operator: c.operator,
|
|
203
|
+
message: `Unknown operator "${c.operator}". Valid operators: ${OPERATORS.join(', ')}.`,
|
|
204
|
+
});
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
// Per-operator structural validation
|
|
208
|
+
switch (c.operator) {
|
|
209
|
+
case 'between':
|
|
210
|
+
if (c.values.length !== 2) {
|
|
211
|
+
errors.push({
|
|
212
|
+
conditionIndex: i,
|
|
213
|
+
attribute: c.attribute,
|
|
214
|
+
operator: c.operator,
|
|
215
|
+
message: `Operator "between" requires exactly 2 values, got ${c.values.length}.`,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
break;
|
|
219
|
+
case 'in':
|
|
220
|
+
case 'not_in':
|
|
221
|
+
if (c.values.length === 0) {
|
|
222
|
+
errors.push({
|
|
223
|
+
conditionIndex: i,
|
|
224
|
+
attribute: c.attribute,
|
|
225
|
+
operator: c.operator,
|
|
226
|
+
message: `Operator "${c.operator}" requires at least 1 value.`,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
else if (c.values.length > IN_LIST_MAX) {
|
|
230
|
+
errors.push({
|
|
231
|
+
conditionIndex: i,
|
|
232
|
+
attribute: c.attribute,
|
|
233
|
+
operator: c.operator,
|
|
234
|
+
message: `Operator "${c.operator}" supports at most ${IN_LIST_MAX} values, got ${c.values.length}.`,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
break;
|
|
238
|
+
case 'exists':
|
|
239
|
+
case 'not_exists':
|
|
240
|
+
if (c.values.length !== 0) {
|
|
241
|
+
errors.push({
|
|
242
|
+
conditionIndex: i,
|
|
243
|
+
attribute: c.attribute,
|
|
244
|
+
operator: c.operator,
|
|
245
|
+
message: `Operator "${c.operator}" takes no values, got ${c.values.length}.`,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
break;
|
|
249
|
+
case 'regex':
|
|
250
|
+
if (c.values.length !== 1) {
|
|
251
|
+
errors.push({
|
|
252
|
+
conditionIndex: i,
|
|
253
|
+
attribute: c.attribute,
|
|
254
|
+
operator: c.operator,
|
|
255
|
+
message: `Operator "regex" requires exactly 1 value, got ${c.values.length}.`,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
try {
|
|
260
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
261
|
+
const _ = new RegExp(String(c.values[0]));
|
|
262
|
+
}
|
|
263
|
+
catch (e) {
|
|
264
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
265
|
+
errors.push({
|
|
266
|
+
conditionIndex: i,
|
|
267
|
+
attribute: c.attribute,
|
|
268
|
+
operator: c.operator,
|
|
269
|
+
message: `Invalid regex pattern: ${msg}`,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
break;
|
|
274
|
+
default:
|
|
275
|
+
// Most binary operators expect exactly 1 value
|
|
276
|
+
if (c.values.length !== 1) {
|
|
277
|
+
errors.push({
|
|
278
|
+
conditionIndex: i,
|
|
279
|
+
attribute: c.attribute,
|
|
280
|
+
operator: c.operator,
|
|
281
|
+
message: `Operator "${c.operator}" requires exactly 1 value, got ${c.values.length}.`,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
// Type-vs-operator compatibility (only when the attribute's type is known)
|
|
287
|
+
const type = attributeTypes[c.attribute];
|
|
288
|
+
if (type && !isOperatorValidForType(c.operator, type)) {
|
|
289
|
+
errors.push({
|
|
290
|
+
conditionIndex: i,
|
|
291
|
+
attribute: c.attribute,
|
|
292
|
+
operator: c.operator,
|
|
293
|
+
message: `Operator "${c.operator}" cannot be used with attribute "${c.attribute}" of type ${type}. Valid operators for ${type}: ${validOperatorsForType(type).join(', ')}.`,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
return errors;
|
|
298
|
+
}
|
|
299
|
+
//# sourceMappingURL=operators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operators.js","sourceRoot":"","sources":["../../src/flags/operators.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { EvalContext } from './evaluator.js';
|
|
2
|
+
/** Canonical HTTP header carrying the serialized eval context. */
|
|
3
|
+
export declare const BRIDGE_CONTEXT_HEADER: "x-bridge-context";
|
|
4
|
+
/** Serialize an eval context into a base64url-encoded JSON string. */
|
|
5
|
+
export declare function serializeContext(ctx: EvalContext): string;
|
|
6
|
+
/**
|
|
7
|
+
* Parse the header value back into an EvalContext. Returns `undefined` if the
|
|
8
|
+
* value is missing, malformed, or carries an unknown wire version. Callers
|
|
9
|
+
* should treat undefined as "no context shipped" — never throw on the request
|
|
10
|
+
* path.
|
|
11
|
+
*/
|
|
12
|
+
export declare function deserializeContext(headerValue: string | undefined | null): EvalContext | undefined;
|
|
13
|
+
export declare function serverInstanceId(): string;
|
|
14
|
+
/** Test-only — reset the cached server-instance id. */
|
|
15
|
+
export declare function __resetServerInstanceId(): void;
|
|
16
|
+
//# sourceMappingURL=propagation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"propagation.d.ts","sourceRoot":"","sources":["../../src/flags/propagation.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAOlD,kEAAkE;AAClE,eAAO,MAAM,qBAAqB,EAAG,kBAA2B,CAAC;AAWjE,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,WAAW,GAAG,MAAM,CAMzD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,WAAW,GAAG,SAAS,CAoBlG;AAcD,wBAAgB,gBAAgB,IAAI,MAAM,CAKzC;AAED,uDAAuD;AACvD,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C"}
|