@gradual-so/sdk 0.7.5 → 0.8.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/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';function E(n){let e=0;for(let t=0;t<n.length;t++){let i=n.charCodeAt(t);e=(e<<5)-e+i,e|=0;}return Math.abs(e)}function f(n,e,t){let i=e[t.bucketContextKind]?.[t.bucketAttributeKey],o=t.seed??"",r=`${n}:${o}:${String(i??"anonymous")}`;return E(r)%1e5}function p(n,e,t){let i=0;for(let r of n.variations)if(i+=r.weight,e<i)return t[r.variationKey];let o=n.variations.at(-1);return o?t[o.variationKey]:void 0}function S(n,e){let{contextKind:t,attributeKey:i,operator:o,value:r}=n,a=e[t]?.[i];switch(o){case "equals":return a===r;case "not_equals":return a!==r;case "contains":return typeof a=="string"&&typeof r=="string"||Array.isArray(a)?a.includes(r):false;case "not_contains":return typeof a=="string"&&typeof r=="string"||Array.isArray(a)?!a.includes(r):true;case "starts_with":return typeof a=="string"&&typeof r=="string"?a.startsWith(r):false;case "ends_with":return typeof a=="string"&&typeof r=="string"?a.endsWith(r):false;case "greater_than":return typeof a=="number"&&typeof r=="number"?a>r:false;case "less_than":return typeof a=="number"&&typeof r=="number"?a<r:false;case "greater_than_or_equal":return typeof a=="number"&&typeof r=="number"?a>=r:false;case "less_than_or_equal":return typeof a=="number"&&typeof r=="number"?a<=r:false;case "in":return Array.isArray(r)?r.includes(a):false;case "not_in":return Array.isArray(r)?!r.includes(a):true;case "exists":return a!=null;case "not_exists":return a==null;default:return false}}function y(n,e){return n.every(t=>S(t,e))}function K(n,e){return y(n.conditions,e)}function x(n,e,t){switch(n.type){case "individual":return n.contextKind&&n.attributeKey&&n.attributeValue!==void 0?e[n.contextKind]?.[n.attributeKey]===n.attributeValue:false;case "rule":return n.conditions?y(n.conditions,e):false;case "segment":if(n.segmentKey){let i=t[n.segmentKey];if(i)return K(i,e)}return false;default:return false}}function C(n,e,t,i){if(n.rollout){let o=f(e,t,n.rollout),r=p(n.rollout,o,i);if(r){let a=Object.keys(i).find(s=>i[s]===r);return a?{variation:r,variationKey:a}:void 0}return}if(n.variationKey){let o=i[n.variationKey];return o?{variation:o,variationKey:n.variationKey}:void 0}}function T(n,e){if(n.defaultRollout){let t=f(n.key,e,n.defaultRollout),i=p(n.defaultRollout,t,n.variations);if(i){let o=Object.keys(n.variations).find(r=>n.variations[r]===i);return o?{variation:i,variationKey:o}:void 0}return}if(n.defaultVariationKey){let t=n.variations[n.defaultVariationKey];return t?{variation:t,variationKey:n.defaultVariationKey}:void 0}}function d(n,e,t){if(!n.enabled)return {value:n.variations[n.offVariationKey]?.value,variationKey:n.offVariationKey,reason:"FLAG_DISABLED"};let i=[...n.targets].sort((r,a)=>r.sortOrder-a.sortOrder);for(let r of i)if(x(r,e,t)){let a=C(r,n.key,e,n.variations);if(a)return {value:a.variation.value,variationKey:a.variationKey,reason:"TARGET_MATCH",matchedTargetName:r.name}}let o=T(n,e);return o?{value:o.variation.value,variationKey:o.variationKey,reason:n.defaultRollout?"DEFAULT_ROLLOUT":"DEFAULT_VARIATION"}:{value:void 0,variationKey:void 0,reason:"DEFAULT_VARIATION"}}var R="0.7.5",k=globalThis,u=k.document,v=class{events=[];timer=null;options;onVisibilityChange=null;constructor(e){this.options=e,this.timer=setInterval(()=>this.flush(),this.options.flushIntervalMs),u?.addEventListener&&(this.onVisibilityChange=()=>{u.visibilityState==="hidden"&&this.flushBeacon();},u.addEventListener("visibilitychange",this.onVisibilityChange));}push(e){this.events.push(e),this.events.length>=this.options.maxBatchSize&&this.flush();}buildPayload(e){return {meta:{...this.options.meta,sdkVersion:R},events:e}}flush(){if(this.events.length===0)return;let e=this.events.splice(0,this.options.maxBatchSize),t=this.buildPayload(e);fetch(`${this.options.baseUrl}/sdk/evaluations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`},body:JSON.stringify(t)}).catch(()=>{});}flushBeacon(){if(this.events.length===0)return;let e=this.events.splice(0,this.options.maxBatchSize),t=this.buildPayload(e);fetch(`${this.options.baseUrl}/sdk/evaluations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`},body:JSON.stringify(t),keepalive:true}).catch(()=>{});}destroy(){this.timer&&(clearInterval(this.timer),this.timer=null),this.onVisibilityChange&&u?.removeEventListener&&u.removeEventListener("visibilitychange",this.onVisibilityChange),this.flush();}};var w="https://worker.gradual.so/api/v1";function O(){try{let n=globalThis,e=n.navigator;if(e&&e.product==="ReactNative")return "react-native";let t=n.window;if(t&&typeof t.document<"u")return "browser";if(n.process?.versions?.node)return "node";if(typeof globalThis<"u")return "edge"}catch{}return "unknown"}var V=O(),m=globalThis.process,D=typeof m?.hrtime?.bigint=="function";function h(){return D?m.hrtime.bigint():typeof performance<"u"?performance.now():Date.now()}function g(n){let e=h();return typeof n=="bigint"&&typeof e=="bigint"?Number((e-n)/1000n):Math.round((e-n)*1e3)}var c=class{apiKey;environment;baseUrl;initPromise;snapshot=null;identifiedContext={};updateListeners=new Set;eventBuffer=null;eventsEnabled;eventsFlushIntervalMs;eventsMaxBatchSize;sync;constructor(e){this.apiKey=e.apiKey,this.environment=e.environment,this.baseUrl=e.baseUrl??w,this.eventsEnabled=e.events?.enabled??true,this.eventsFlushIntervalMs=e.events?.flushIntervalMs??3e4,this.eventsMaxBatchSize=e.events?.maxBatchSize??100,this.initPromise=this.init(),this.sync={isEnabled:this.isEnabledSync.bind(this),get:this.getSync.bind(this),evaluate:this.evaluateSync.bind(this),track:this.trackSync.bind(this)};let t=e.polling?.enabled??true,i=e.polling?.intervalMs??1e4;t&&this.initPromise.then(()=>{setInterval(async()=>{try{let o=this.snapshot?.version;if(await this.refresh(),this.snapshot&&this.snapshot.version!==o)for(let r of this.updateListeners)r();}catch(o){console.warn("Gradual: Polling refresh failed",o);}},i);});}async init(){let e=await fetch(`${this.baseUrl}/sdk/init`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:this.apiKey})});if(!e.ok){let o=await e.json().catch(()=>({}));throw new Error(`Gradual: Failed to initialize - ${o.error??e.statusText}`)}let t=await e.json();if(!t.valid)throw new Error(`Gradual: Invalid API key - ${t.error??"Unknown error"}`);let i=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!i.ok){let o=await i.json().catch(()=>({}));throw new Error(`Gradual: Failed to fetch snapshot - ${o.error??i.statusText}`)}this.snapshot=await i.json(),this.eventsEnabled&&this.snapshot.meta&&(this.eventBuffer=new v({baseUrl:this.baseUrl,apiKey:this.apiKey,meta:{projectId:this.snapshot.meta.projectId,organizationId:this.snapshot.meta.organizationId,environmentId:this.snapshot.meta.environmentId,sdkPlatform:V},flushIntervalMs:this.eventsFlushIntervalMs,maxBatchSize:this.eventsMaxBatchSize}));}ensureReady(){if(!this.snapshot)throw new Error("Gradual: SDK not ready. Use await ready() or async methods.");return this.snapshot}mergeContext(e){let t={},i=new Set([...Object.keys(this.identifiedContext),...Object.keys(e?.context??{})]);for(let o of i)t[o]={...this.identifiedContext[o],...e?.context?.[o]};return t}evaluate(e,t){let i=this.ensureReady();if(!i.flags)return;let o=i.flags[e];if(!o){this.trackEvent({flagKey:e,variationKey:void 0,value:void 0,reason:"FLAG_NOT_FOUND",context:t,flagConfigVersion:i.version});return}let r=h(),a;try{a=d(o,t,i.segments??{});}catch(l){a={value:void 0,variationKey:void 0,reason:"ERROR",errorDetail:l instanceof Error?l.message:String(l)};}let s=g(r);return this.trackEvent({flagKey:e,variationKey:a.variationKey,value:a.value,reason:a.reason,context:t,matchedTargetName:a.matchedTargetName,flagConfigVersion:i.version,errorDetail:a.errorDetail,evaluationDurationUs:s}),a.value}trackEvent(e){if(!this.eventBuffer)return;let{context:t}=e,i=Object.keys(t),o={};for(let a of i)o[a]=Object.keys(t[a]??{});let r=i.length===0||i.every(a=>Object.keys(t[a]??{}).length===0);this.eventBuffer.push({flagKey:e.flagKey,variationKey:e.variationKey,value:e.value,reason:e.reason,contextKinds:i,contextKeys:o,timestamp:Date.now(),matchedTargetName:e.matchedTargetName,flagConfigVersion:e.flagConfigVersion,errorDetail:e.errorDetail,evaluationDurationUs:e.evaluationDurationUs,isAnonymous:r});}async ready(){await this.initPromise;}isReady(){return this.snapshot!==null}async isEnabled(e,t){await this.initPromise;let i=this.evaluate(e,this.mergeContext(t));return typeof i=="boolean"?i:false}async get(e,t){await this.initPromise;let i=this.evaluate(e,this.mergeContext(t));return i??t.fallback}isEnabledSync(e,t){let i=this.evaluate(e,this.mergeContext(t));return typeof i=="boolean"?i:false}getSync(e,t){let i=this.evaluate(e,this.mergeContext(t));return i??t.fallback}evaluateSync(e,t){let i=this.ensureReady(),o=this.mergeContext(t);if(!i.flags)return {value:void 0,variationKey:void 0,reason:"FLAG_NOT_FOUND",flagConfigVersion:i.version};let r=i.flags[e];if(!r)return {value:void 0,variationKey:void 0,reason:"FLAG_NOT_FOUND",flagConfigVersion:i.version};let a=h(),s;try{s=d(r,o,i.segments??{});}catch(l){s={value:void 0,variationKey:void 0,reason:"ERROR",errorDetail:l instanceof Error?l.message:String(l)};}return {value:s.value,variationKey:s.variationKey,reason:s.reason,matchedTargetName:s.matchedTargetName,errorDetail:s.errorDetail,evaluationDurationUs:g(a),flagConfigVersion:i.version}}trackSync(e,t,i){this.trackEvent({flagKey:e,variationKey:t.variationKey,value:t.value,reason:t.reason,context:this.mergeContext({context:i}),matchedTargetName:t.matchedTargetName,flagConfigVersion:t.flagConfigVersion,errorDetail:t.errorDetail,evaluationDurationUs:t.evaluationDurationUs});}identify(e){this.identifiedContext={...e};}reset(){this.identifiedContext={};}async refresh(){let e=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!e.ok){let t=await e.json().catch(()=>({}));throw new Error(`Gradual: Failed to refresh - ${t.error??e.statusText}`)}this.snapshot=await e.json();}getSnapshot(){return this.snapshot}onUpdate(e){return this.updateListeners.add(e),()=>this.updateListeners.delete(e)}close(){this.eventBuffer&&(this.eventBuffer.destroy(),this.eventBuffer=null);}};function _(n){return new c(n)}
2
- exports.createGradual=_;exports.evaluateFlag=d;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';function b(n){let t=0;for(let e=0;e<n.length;e++){let a=n.charCodeAt(e);t=(t<<5)-t+a,t|=0;}return Math.abs(t)}function f(n,t,e){let a=t[e.bucketContextKind]?.[e.bucketAttributeKey],o=e.seed??"",i=`${n}:${o}:${String(a??"anonymous")}`;return b(i)%1e5}function p(n,t,e){let a=0,o;for(let r of n.variations)if(a+=r.weight,t<a){o=r;break}if(o||(o=n.variations.at(-1)),!o)return;let i=e[o.variationKey];if(i)return {variation:i,variationKey:o.variationKey,matchedWeight:o.weight,bucketValue:t}}function E(n,t){let{contextKind:e,attributeKey:a,operator:o,value:i}=n,r=t[e]?.[a];switch(o){case "equals":return r===i;case "not_equals":return r!==i;case "contains":return typeof r=="string"&&typeof i=="string"||Array.isArray(r)?r.includes(i):false;case "not_contains":return typeof r=="string"&&typeof i=="string"||Array.isArray(r)?!r.includes(i):true;case "starts_with":return typeof r=="string"&&typeof i=="string"?r.startsWith(i):false;case "ends_with":return typeof r=="string"&&typeof i=="string"?r.endsWith(i):false;case "greater_than":return typeof r=="number"&&typeof i=="number"?r>i:false;case "less_than":return typeof r=="number"&&typeof i=="number"?r<i:false;case "greater_than_or_equal":return typeof r=="number"&&typeof i=="number"?r>=i:false;case "less_than_or_equal":return typeof r=="number"&&typeof i=="number"?r<=i:false;case "in":return Array.isArray(i)?i.includes(r):false;case "not_in":return Array.isArray(i)?!i.includes(r):true;case "exists":return r!=null;case "not_exists":return r==null;default:return false}}function y(n,t){return n.every(e=>E(e,t))}function S(n,t){return y(n.conditions,t)}function R(n,t,e){switch(n.type){case "individual":return n.contextKind&&n.attributeKey&&n.attributeValue!==void 0?t[n.contextKind]?.[n.attributeKey]===n.attributeValue:false;case "rule":return n.conditions?y(n.conditions,t):false;case "segment":if(n.segmentKey){let a=e[n.segmentKey];if(a)return S(a,t)}return false;default:return false}}function x(n,t,e,a){if(n.rollout){let o=f(t,e,n.rollout);return p(n.rollout,o,a)}if(n.variationKey){let o=a[n.variationKey];if(o)return {variation:o,variationKey:n.variationKey,matchedWeight:1e5,bucketValue:0}}}function K(n,t){if(n.defaultRollout){let e=f(n.key,t,n.defaultRollout);return p(n.defaultRollout,e,n.variations)}if(n.defaultVariationKey){let e=n.variations[n.defaultVariationKey];if(e)return {variation:e,variationKey:n.defaultVariationKey,matchedWeight:1e5,bucketValue:0}}}function T(n){return {type:"rule_match",ruleId:n.id??"",ruleName:n.name}}function c(n){return {type:"percentage_rollout",percentage:n.matchedWeight/1e3,bucket:n.bucketValue}}function v(n,t,e){if(!n.enabled)return {value:n.variations[n.offVariationKey]?.value,variationKey:n.offVariationKey,reasons:[{type:"off"}]};let a=[...n.targets].sort((i,r)=>i.sortOrder-r.sortOrder);for(let i of a)if(R(i,t,e)){let r=x(i,n.key,t,n.variations);if(r){let s=[T(i)];return i.rollout&&s.push(c(r)),{value:r.variation.value,variationKey:r.variationKey,reasons:s,matchedTargetName:i.name}}}let o=K(n,t);if(o){let i=[];return n.defaultRollout&&i.push(c(o)),i.push({type:"default"}),{value:o.variation.value,variationKey:o.variationKey,reasons:i}}return {value:void 0,variationKey:void 0,reasons:[{type:"default"}]}}var w="0.8.0",k=globalThis,l=k.document,d=class{events=[];timer=null;options;onVisibilityChange=null;constructor(t){this.options=t,this.timer=setInterval(()=>this.flush(),this.options.flushIntervalMs),l?.addEventListener&&(this.onVisibilityChange=()=>{l.visibilityState==="hidden"&&this.flushBeacon();},l.addEventListener("visibilitychange",this.onVisibilityChange));}push(t){this.events.push(t),this.events.length>=this.options.maxBatchSize&&this.flush();}buildPayload(t){return {meta:{...this.options.meta,sdkVersion:w},events:t}}flush(){if(this.events.length===0)return;let t=this.events.splice(0,this.options.maxBatchSize),e=this.buildPayload(t);fetch(`${this.options.baseUrl}/sdk/evaluations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`},body:JSON.stringify(e)}).catch(()=>{});}flushBeacon(){if(this.events.length===0)return;let t=this.events.splice(0,this.options.maxBatchSize),e=this.buildPayload(t);fetch(`${this.options.baseUrl}/sdk/evaluations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`},body:JSON.stringify(e),keepalive:true}).catch(()=>{});}destroy(){this.timer&&(clearInterval(this.timer),this.timer=null),this.onVisibilityChange&&l?.removeEventListener&&l.removeEventListener("visibilitychange",this.onVisibilityChange),this.flush();}};var C="https://worker.gradual.so/api/v1";function O(){try{let n=globalThis,t=n.navigator;if(t&&t.product==="ReactNative")return "react-native";let e=n.window;if(e&&typeof e.document<"u")return "browser";if(n.process?.versions?.node)return "node";if(typeof globalThis<"u")return "edge"}catch{}return "unknown"}var I=O(),g=globalThis.process,V=typeof g?.hrtime?.bigint=="function";function m(){return V?g.hrtime.bigint():typeof performance<"u"?performance.now():Date.now()}function _(n){let t=m();return typeof n=="bigint"&&typeof t=="bigint"?Number((t-n)/1000n):Math.round((t-n)*1e3)}var h=class{apiKey;environment;baseUrl;initPromise;snapshot=null;identifiedContext={};updateListeners=new Set;eventBuffer=null;eventsEnabled;eventsFlushIntervalMs;eventsMaxBatchSize;sync;constructor(t){this.apiKey=t.apiKey,this.environment=t.environment,this.baseUrl=t.baseUrl??C,this.eventsEnabled=t.events?.enabled??true,this.eventsFlushIntervalMs=t.events?.flushIntervalMs??3e4,this.eventsMaxBatchSize=t.events?.maxBatchSize??100,this.initPromise=this.init(),this.sync={isEnabled:this.isEnabledSync.bind(this),get:this.getSync.bind(this),evaluate:this.evaluateSync.bind(this),track:this.trackSync.bind(this)};let e=t.polling?.enabled??true,a=t.polling?.intervalMs??1e4;e&&this.initPromise.then(()=>{setInterval(async()=>{try{let o=this.snapshot?.version;if(await this.refresh(),this.snapshot&&this.snapshot.version!==o)for(let i of this.updateListeners)i();}catch(o){console.warn("Gradual: Polling refresh failed",o);}},a);});}async init(){let t=await fetch(`${this.baseUrl}/sdk/init`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:this.apiKey})});if(!t.ok){let o=await t.json().catch(()=>({}));throw new Error(`Gradual: Failed to initialize - ${o.error??t.statusText}`)}let e=await t.json();if(!e.valid)throw new Error(`Gradual: Invalid API key - ${e.error??"Unknown error"}`);let a=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!a.ok){let o=await a.json().catch(()=>({}));throw new Error(`Gradual: Failed to fetch snapshot - ${o.error??a.statusText}`)}this.snapshot=await a.json(),this.eventsEnabled&&this.snapshot.meta&&(this.eventBuffer=new d({baseUrl:this.baseUrl,apiKey:this.apiKey,meta:{projectId:this.snapshot.meta.projectId,organizationId:this.snapshot.meta.organizationId,environmentId:this.snapshot.meta.environmentId,sdkPlatform:I},flushIntervalMs:this.eventsFlushIntervalMs,maxBatchSize:this.eventsMaxBatchSize}));}ensureReady(){if(!this.snapshot)throw new Error("Gradual: SDK not ready. Use await ready() or async methods.");return this.snapshot}mergeContext(t){let e={},a=new Set([...Object.keys(this.identifiedContext),...Object.keys(t?.context??{})]);for(let o of a)e[o]={...this.identifiedContext[o],...t?.context?.[o]};return e}evaluateRaw(t,e){let a=this.ensureReady();if(!a.flags)return {output:null,snapshot:a,durationUs:0};let o=a.flags[t];if(!o)return {output:null,snapshot:a,durationUs:0};let i=m(),r;try{r=v(o,e,a.segments??{});}catch(s){let u=s instanceof Error?s.message:String(s);r={value:void 0,variationKey:void 0,reasons:[{type:"error",detail:u}],errorDetail:u};}return {output:r,snapshot:a,durationUs:_(i)}}buildResult(t,e,a){let o=e.reasons.find(i=>i.type==="rule_match");return {key:t,value:e.value,variationKey:e.variationKey,reasons:e.reasons,ruleId:o?.ruleId,version:a,evaluatedAt:new Date().toISOString()}}evaluateAndTrack(t,e){let{output:a,snapshot:o,durationUs:i}=this.evaluateRaw(t,e);if(!a){this.trackEvent({flagKey:t,variationKey:void 0,value:void 0,reasons:[{type:"error",detail:"FLAG_NOT_FOUND"}],context:e,flagConfigVersion:o.version});return}return this.trackEvent({flagKey:t,variationKey:a.variationKey,value:a.value,reasons:a.reasons,context:e,matchedTargetName:a.matchedTargetName,flagConfigVersion:o.version,errorDetail:a.errorDetail,evaluationDurationUs:i}),a.value}trackEvent(t){if(!this.eventBuffer)return;let{context:e}=t,a=Object.keys(e),o={};for(let r of a)o[r]=Object.keys(e[r]??{});let i=a.length===0||a.every(r=>Object.keys(e[r]??{}).length===0);this.eventBuffer.push({flagKey:t.flagKey,variationKey:t.variationKey,value:t.value,reasons:t.reasons,evaluatedAt:t.evaluatedAt,ruleId:t.ruleId,contextKinds:a,contextKeys:o,timestamp:Date.now(),matchedTargetName:t.matchedTargetName,flagConfigVersion:t.flagConfigVersion,errorDetail:t.errorDetail,evaluationDurationUs:t.evaluationDurationUs,isAnonymous:i});}async ready(){await this.initPromise;}isReady(){return this.snapshot!==null}async isEnabled(t,e){await this.initPromise;let a=this.evaluateAndTrack(t,this.mergeContext(e));return typeof a=="boolean"?a:false}async get(t,e){await this.initPromise;let a=this.evaluateAndTrack(t,this.mergeContext(e));return a??e.fallback}async evaluate(t,e){await this.initPromise;let a=this.mergeContext(e),{output:o,snapshot:i,durationUs:r}=this.evaluateRaw(t,a);if(!o){let u={key:t,value:void 0,variationKey:void 0,reasons:[{type:"error",detail:"FLAG_NOT_FOUND"}],version:i.version,evaluatedAt:new Date().toISOString()};return this.trackEvent({flagKey:t,variationKey:void 0,value:void 0,reasons:u.reasons,evaluatedAt:u.evaluatedAt,context:a,flagConfigVersion:i.version}),u}let s=this.buildResult(t,o,i.version);return this.trackEvent({flagKey:t,variationKey:o.variationKey,value:o.value,reasons:o.reasons,evaluatedAt:s.evaluatedAt,ruleId:s.ruleId,context:a,matchedTargetName:o.matchedTargetName,flagConfigVersion:i.version,errorDetail:o.errorDetail,evaluationDurationUs:r}),s}isEnabledSync(t,e){let a=this.evaluateAndTrack(t,this.mergeContext(e));return typeof a=="boolean"?a:false}getSync(t,e){let a=this.evaluateAndTrack(t,this.mergeContext(e));return a??e.fallback}evaluateSync(t,e){let a=this.mergeContext(e),{output:o,snapshot:i}=this.evaluateRaw(t,a);return o?this.buildResult(t,o,i.version):{key:t,value:void 0,variationKey:void 0,reasons:[{type:"error",detail:"FLAG_NOT_FOUND"}],version:i.version,evaluatedAt:new Date().toISOString()}}trackSync(t,e,a){let o=e.reasons.find(i=>i.type==="rule_match");this.trackEvent({flagKey:t,variationKey:e.variationKey,value:e.value,reasons:e.reasons,evaluatedAt:e.evaluatedAt,ruleId:e.ruleId,context:this.mergeContext({context:a}),matchedTargetName:o?.ruleName,flagConfigVersion:e.version});}identify(t){this.identifiedContext={...t};}reset(){this.identifiedContext={};}async refresh(){let t=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!t.ok){let e=await t.json().catch(()=>({}));throw new Error(`Gradual: Failed to refresh - ${e.error??t.statusText}`)}this.snapshot=await t.json();}getSnapshot(){return this.snapshot}onUpdate(t){return this.updateListeners.add(t),()=>this.updateListeners.delete(t)}close(){this.eventBuffer&&(this.eventBuffer.destroy(),this.eventBuffer=null);}};function A(n){return new h(n)}
2
+ exports.createGradual=A;exports.evaluateFlag=v;//# sourceMappingURL=index.cjs.map
3
3
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/evaluator.ts","../src/event-buffer.ts","../src/client.ts"],"names":["hashString","str","hash","i","char","getBucketValue","flagKey","context","rollout","bucketKey","seed","hashInput","selectVariationFromRollout","bucketValue","variations","cumulative","rv","lastVariation","evaluateCondition","condition","contextKind","attributeKey","operator","value","contextValue","evaluateConditions","conditions","evaluateSegment","segment","evaluateTarget","target","segments","resolveTargetVariation","variation","key","k","resolveDefaultVariation","flag","evaluateFlag","sortedTargets","a","b","resolved","SDK_VERSION","g","doc","EventBuffer","options","event","batch","payload","DEFAULT_BASE_URL","detectPlatform","nav","win","SDK_PLATFORM","proc","hasHrtime","nowNs","elapsedUs","start","end","GradualClient","pollingEnabled","pollingIntervalMs","previousVersion","cb","error","initResponse","initData","snapshotResponse","merged","allKinds","kind","snapshot","startTime","result","err","evaluationDurationUs","params","contextKinds","contextKeys","isAnonymous","detail","response","callback","createGradual"],"mappings":"aAWA,SAASA,CAAAA,CAAWC,CAAAA,CAAqB,CACvC,IAAIC,CAAAA,CAAO,CAAA,CACX,IAAA,IAASC,CAAAA,CAAI,CAAA,CAAGA,CAAAA,CAAIF,CAAAA,CAAI,MAAA,CAAQE,CAAAA,EAAAA,CAAK,CACnC,IAAMC,CAAAA,CAAOH,CAAAA,CAAI,UAAA,CAAWE,CAAC,CAAA,CAE7BD,CAAAA,CAAAA,CAAQA,CAAAA,EAAQ,CAAA,EAAKA,CAAAA,CAAOE,CAAAA,CAE5BF,CAAAA,EAAQ,EACV,CACA,OAAO,KAAK,GAAA,CAAIA,CAAI,CACtB,CAEA,SAASG,CAAAA,CACPC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACQ,CACR,IAAMC,CAAAA,CACJF,CAAAA,CAAQC,CAAAA,CAAQ,iBAAiB,CAAA,GAAIA,CAAAA,CAAQ,kBAAkB,CAAA,CAC3DE,CAAAA,CAAOF,CAAAA,CAAQ,IAAA,EAAQ,EAAA,CACvBG,CAAAA,CAAY,CAAA,EAAGL,CAAO,CAAA,CAAA,EAAII,CAAI,CAAA,CAAA,EAAI,MAAA,CAAOD,GAAa,WAAW,CAAC,CAAA,CAAA,CACxE,OAAOT,CAAAA,CAAWW,CAAS,CAAA,CAAI,GACjC,CAEA,SAASC,CAAAA,CACPJ,CAAAA,CACAK,CAAAA,CACAC,CAAAA,CAC+B,CAC/B,IAAIC,CAAAA,CAAa,CAAA,CAEjB,IAAA,IAAWC,CAAAA,IAAMR,CAAAA,CAAQ,UAAA,CAEvB,GADAO,CAAAA,EAAcC,CAAAA,CAAG,MAAA,CACbH,CAAAA,CAAcE,CAAAA,CAChB,OAAOD,CAAAA,CAAWE,EAAG,YAAY,CAAA,CAIrC,IAAMC,CAAAA,CAAgBT,CAAAA,CAAQ,UAAA,CAAW,EAAA,CAAG,EAAE,CAAA,CAC9C,OAAOS,CAAAA,CAAgBH,CAAAA,CAAWG,CAAAA,CAAc,YAAY,CAAA,CAAI,MAClE,CAEA,SAASC,CAAAA,CACPC,CAAAA,CACAZ,CAAAA,CACS,CACT,GAAM,CAAE,WAAA,CAAAa,CAAAA,CAAa,YAAA,CAAAC,CAAAA,CAAc,QAAA,CAAAC,CAAAA,CAAU,MAAAC,CAAM,CAAA,CAAIJ,CAAAA,CACjDK,CAAAA,CAAejB,CAAAA,CAAQa,CAAW,CAAA,GAAIC,CAAY,CAAA,CAExD,OAAQC,CAAAA,EACN,KAAK,QAAA,CACH,OAAOE,CAAAA,GAAiBD,CAAAA,CAE1B,KAAK,YAAA,CACH,OAAOC,CAAAA,GAAiBD,CAAAA,CAE1B,KAAK,UAAA,CAIH,OAHI,OAAOC,CAAAA,EAAiB,QAAA,EAAY,OAAOD,CAAAA,EAAU,UAGrD,KAAA,CAAM,OAAA,CAAQC,CAAY,CAAA,CACrBA,CAAAA,CAAa,QAAA,CAASD,CAAK,CAAA,CAE7B,KAAA,CAET,KAAK,cAAA,CAIH,OAHI,OAAOC,CAAAA,EAAiB,QAAA,EAAY,OAAOD,CAAAA,EAAU,QAAA,EAGrD,KAAA,CAAM,OAAA,CAAQC,CAAY,CAAA,CACrB,CAACA,CAAAA,CAAa,QAAA,CAASD,CAAK,CAAA,CAE9B,IAAA,CAET,KAAK,aAAA,CACH,OAAI,OAAOC,CAAAA,EAAiB,QAAA,EAAY,OAAOD,CAAAA,EAAU,QAAA,CAChDC,CAAAA,CAAa,UAAA,CAAWD,CAAK,CAAA,CAE/B,KAAA,CAET,KAAK,WAAA,CACH,OAAI,OAAOC,CAAAA,EAAiB,QAAA,EAAY,OAAOD,CAAAA,EAAU,QAAA,CAChDC,CAAAA,CAAa,QAAA,CAASD,CAAK,CAAA,CAE7B,KAAA,CAET,KAAK,cAAA,CACH,OAAI,OAAOC,CAAAA,EAAiB,UAAY,OAAOD,CAAAA,EAAU,QAAA,CAChDC,CAAAA,CAAeD,CAAAA,CAEjB,KAAA,CAET,KAAK,WAAA,CACH,OAAI,OAAOC,CAAAA,EAAiB,QAAA,EAAY,OAAOD,CAAAA,EAAU,QAAA,CAChDC,CAAAA,CAAeD,CAAAA,CAEjB,KAAA,CAET,KAAK,uBAAA,CACH,OAAI,OAAOC,CAAAA,EAAiB,QAAA,EAAY,OAAOD,CAAAA,EAAU,QAAA,CAChDC,CAAAA,EAAgBD,CAAAA,CAElB,KAAA,CAET,KAAK,oBAAA,CACH,OAAI,OAAOC,CAAAA,EAAiB,QAAA,EAAY,OAAOD,CAAAA,EAAU,QAAA,CAChDC,CAAAA,EAAgBD,CAAAA,CAElB,KAAA,CAET,KAAK,IAAA,CACH,OAAI,KAAA,CAAM,OAAA,CAAQA,CAAK,CAAA,CACdA,CAAAA,CAAM,QAAA,CAASC,CAAY,CAAA,CAE7B,KAAA,CAET,KAAK,QAAA,CACH,OAAI,KAAA,CAAM,OAAA,CAAQD,CAAK,CAAA,CACd,CAACA,CAAAA,CAAM,QAAA,CAASC,CAAY,CAAA,CAE9B,IAAA,CAET,KAAK,QAAA,CACH,OAAqCA,CAAAA,EAAiB,IAAA,CAExD,KAAK,YAAA,CACH,OAAqCA,CAAAA,EAAiB,IAAA,CAExD,QACE,OAAO,MACX,CACF,CAEA,SAASC,CAAAA,CACPC,CAAAA,CACAnB,CAAAA,CACS,CACT,OAAOmB,CAAAA,CAAW,KAAA,CAAOP,CAAAA,EAAcD,CAAAA,CAAkBC,EAAWZ,CAAO,CAAC,CAC9E,CAEA,SAASoB,CAAAA,CACPC,CAAAA,CACArB,CAAAA,CACS,CACT,OAAOkB,CAAAA,CAAmBG,CAAAA,CAAQ,UAAA,CAAYrB,CAAO,CACvD,CAEA,SAASsB,CAAAA,CACPC,CAAAA,CACAvB,CAAAA,CACAwB,CAAAA,CACS,CACT,OAAQD,CAAAA,CAAO,IAAA,EACb,KAAK,YAAA,CACH,OACEA,CAAAA,CAAO,aACPA,CAAAA,CAAO,YAAA,EACPA,CAAAA,CAAO,cAAA,GAAmB,MAAA,CAGxBvB,CAAAA,CAAQuB,CAAAA,CAAO,WAAW,CAAA,GAAIA,CAAAA,CAAO,YAAY,CAAA,GACjDA,CAAAA,CAAO,cAAA,CAGJ,KAAA,CAET,KAAK,MAAA,CACH,OAAIA,CAAAA,CAAO,UAAA,CACFL,CAAAA,CAAmBK,CAAAA,CAAO,UAAA,CAAYvB,CAAO,CAAA,CAE/C,KAAA,CAET,KAAK,SAAA,CACH,GAAIuB,CAAAA,CAAO,WAAY,CACrB,IAAMF,CAAAA,CAAUG,CAAAA,CAASD,CAAAA,CAAO,UAAU,CAAA,CAC1C,GAAIF,CAAAA,CACF,OAAOD,CAAAA,CAAgBC,CAAAA,CAASrB,CAAO,CAE3C,CACA,OAAO,MAAA,CAET,QACE,OAAO,MACX,CACF,CAOA,SAASyB,CAAAA,CACPF,CAAAA,CACAxB,CAAAA,CACAC,CAAAA,CACAO,CAAAA,CAC+B,CAC/B,GAAIgB,EAAO,OAAA,CAAS,CAClB,IAAMjB,CAAAA,CAAcR,CAAAA,CAAeC,CAAAA,CAASC,CAAAA,CAASuB,CAAAA,CAAO,OAAO,CAAA,CAC7DG,CAAAA,CAAYrB,CAAAA,CAChBkB,CAAAA,CAAO,OAAA,CACPjB,CAAAA,CACAC,CACF,CAAA,CACA,GAAImB,CAAAA,CAAW,CACb,IAAMC,CAAAA,CAAM,MAAA,CAAO,IAAA,CAAKpB,CAAU,CAAA,CAAE,IAAA,CACjCqB,CAAAA,EAAMrB,CAAAA,CAAWqB,CAAC,IAAMF,CAC3B,CAAA,CACA,OAAOC,CAAAA,CAAM,CAAE,SAAA,CAAAD,CAAAA,CAAW,YAAA,CAAcC,CAAI,CAAA,CAAI,MAClD,CACA,MACF,CAEA,GAAIJ,CAAAA,CAAO,YAAA,CAAc,CACvB,IAAMG,CAAAA,CAAYnB,CAAAA,CAAWgB,CAAAA,CAAO,YAAY,CAAA,CAChD,OAAOG,CAAAA,CACH,CAAE,SAAA,CAAAA,CAAAA,CAAW,YAAA,CAAcH,EAAO,YAAa,CAAA,CAC/C,MACN,CAGF,CAEA,SAASM,CAAAA,CACPC,CAAAA,CACA9B,CAAAA,CAC+B,CAC/B,GAAI8B,CAAAA,CAAK,cAAA,CAAgB,CACvB,IAAMxB,CAAAA,CAAcR,CAAAA,CAAegC,CAAAA,CAAK,GAAA,CAAK9B,CAAAA,CAAS8B,CAAAA,CAAK,cAAc,CAAA,CACnEJ,CAAAA,CAAYrB,CAAAA,CAChByB,CAAAA,CAAK,cAAA,CACLxB,CAAAA,CACAwB,CAAAA,CAAK,UACP,EACA,GAAIJ,CAAAA,CAAW,CACb,IAAMC,CAAAA,CAAM,MAAA,CAAO,IAAA,CAAKG,CAAAA,CAAK,UAAU,CAAA,CAAE,IAAA,CACtCF,CAAAA,EAAME,CAAAA,CAAK,UAAA,CAAWF,CAAC,CAAA,GAAMF,CAChC,CAAA,CACA,OAAOC,CAAAA,CAAM,CAAE,SAAA,CAAAD,CAAAA,CAAW,YAAA,CAAcC,CAAI,CAAA,CAAI,MAClD,CACA,MACF,CAEA,GAAIG,CAAAA,CAAK,mBAAA,CAAqB,CAC5B,IAAMJ,CAAAA,CAAYI,CAAAA,CAAK,UAAA,CAAWA,CAAAA,CAAK,mBAAmB,CAAA,CAC1D,OAAOJ,CAAAA,CACH,CAAE,SAAA,CAAAA,CAAAA,CAAW,YAAA,CAAcI,CAAAA,CAAK,mBAAoB,CAAA,CACpD,MACN,CAGF,CAEO,SAASC,CAAAA,CACdD,CAAAA,CACA9B,CAAAA,CACAwB,CAAAA,CACkB,CAClB,GAAI,CAACM,EAAK,OAAA,CAER,OAAO,CACL,KAAA,CAFmBA,CAAAA,CAAK,UAAA,CAAWA,CAAAA,CAAK,eAAe,CAAA,EAElC,KAAA,CACrB,YAAA,CAAcA,CAAAA,CAAK,eAAA,CACnB,MAAA,CAAQ,eACV,CAAA,CAGF,IAAME,CAAAA,CAAgB,CAAC,GAAGF,CAAAA,CAAK,OAAO,CAAA,CAAE,IAAA,CACtC,CAACG,CAAAA,CAAGC,CAAAA,GAAMD,CAAAA,CAAE,SAAA,CAAYC,CAAAA,CAAE,SAC5B,CAAA,CAEA,IAAA,IAAWX,CAAAA,IAAUS,CAAAA,CACnB,GAAIV,CAAAA,CAAeC,CAAAA,CAAQvB,CAAAA,CAASwB,CAAQ,CAAA,CAAG,CAC7C,IAAMW,CAAAA,CAAWV,CAAAA,CACfF,CAAAA,CACAO,CAAAA,CAAK,GAAA,CACL9B,CAAAA,CACA8B,CAAAA,CAAK,UACP,CAAA,CACA,GAAIK,CAAAA,CACF,OAAO,CACL,KAAA,CAAOA,CAAAA,CAAS,SAAA,CAAU,KAAA,CAC1B,YAAA,CAAcA,EAAS,YAAA,CACvB,MAAA,CAAQ,cAAA,CACR,iBAAA,CAAmBZ,CAAAA,CAAO,IAC5B,CAEJ,CAGF,IAAMY,CAAAA,CAAWN,CAAAA,CAAwBC,CAAAA,CAAM9B,CAAO,CAAA,CACtD,OAAImC,CAAAA,CACK,CACL,KAAA,CAAOA,CAAAA,CAAS,SAAA,CAAU,KAAA,CAC1B,YAAA,CAAcA,CAAAA,CAAS,YAAA,CACvB,MAAA,CAAQL,CAAAA,CAAK,cAAA,CAAiB,iBAAA,CAAoB,mBACpD,CAAA,CAGK,CACL,KAAA,CAAO,MAAA,CACP,YAAA,CAAc,MAAA,CACd,MAAA,CAAQ,mBACV,CACF,CCxTO,IAAMM,CAAAA,CAAc,OAAA,CAerBC,CAAAA,CAAI,UAAA,CACJC,CAAAA,CAAMD,CAAAA,CAAE,QAAA,CAODE,CAAAA,CAAN,KAAkB,CACN,MAAA,CAA4B,EAAC,CACtC,KAAA,CAA+C,IAAA,CACtC,OAAA,CACA,kBAAA,CAA0C,IAAA,CAE3D,WAAA,CAAYC,CAAAA,CAA6B,CACvC,KAAK,OAAA,CAAUA,CAAAA,CACf,IAAA,CAAK,KAAA,CAAQ,WAAA,CAAY,IAAM,IAAA,CAAK,KAAA,EAAM,CAAG,IAAA,CAAK,OAAA,CAAQ,eAAe,CAAA,CAErEF,CAAAA,EAAK,gBAAA,GACP,IAAA,CAAK,kBAAA,CAAqB,IAAM,CAC1BA,CAAAA,CAAI,eAAA,GAAoB,QAAA,EAC1B,IAAA,CAAK,WAAA,GAET,CAAA,CACAA,CAAAA,CAAI,gBAAA,CAAiB,kBAAA,CAAoB,IAAA,CAAK,kBAAkB,CAAA,EAEpE,CAEA,IAAA,CAAKG,CAAAA,CAA8B,CACjC,IAAA,CAAK,MAAA,CAAO,IAAA,CAAKA,CAAK,CAAA,CAClB,IAAA,CAAK,MAAA,CAAO,MAAA,EAAU,IAAA,CAAK,OAAA,CAAQ,YAAA,EACrC,IAAA,CAAK,KAAA,GAET,CAEQ,YAAA,CAAaC,CAAAA,CAAkD,CACrE,OAAO,CACL,IAAA,CAAM,CACJ,GAAG,IAAA,CAAK,OAAA,CAAQ,KAChB,UAAA,CAAYN,CACd,CAAA,CACA,MAAA,CAAQM,CACV,CACF,CAEA,KAAA,EAAc,CACZ,GAAI,IAAA,CAAK,MAAA,CAAO,MAAA,GAAW,CAAA,CACzB,OAEF,IAAMA,CAAAA,CAAQ,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,CAAA,CAAG,IAAA,CAAK,OAAA,CAAQ,YAAY,CAAA,CACvDC,CAAAA,CAAU,IAAA,CAAK,YAAA,CAAaD,CAAK,CAAA,CAEvC,MAAM,CAAA,EAAG,IAAA,CAAK,OAAA,CAAQ,OAAO,CAAA,gBAAA,CAAA,CAAoB,CAC/C,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CACP,cAAA,CAAgB,kBAAA,CAChB,aAAA,CAAe,CAAA,OAAA,EAAU,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAA,CAC9C,CAAA,CACA,IAAA,CAAM,IAAA,CAAK,SAAA,CAAUC,CAAO,CAC9B,CAAC,CAAA,CAAE,KAAA,CAAM,IAAM,CAEf,CAAC,EACH,CAMQ,WAAA,EAAoB,CAC1B,GAAI,IAAA,CAAK,MAAA,CAAO,MAAA,GAAW,CAAA,CACzB,OAGF,IAAMD,CAAAA,CAAQ,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,CAAA,CAAG,IAAA,CAAK,OAAA,CAAQ,YAAY,CAAA,CACvDC,CAAAA,CAAU,IAAA,CAAK,YAAA,CAAaD,CAAK,CAAA,CAEvC,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,OAAA,CAAQ,OAAO,CAAA,gBAAA,CAAA,CAAoB,CAC/C,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CACP,cAAA,CAAgB,kBAAA,CAChB,aAAA,CAAe,CAAA,OAAA,EAAU,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAA,CAC9C,CAAA,CACA,IAAA,CAAM,IAAA,CAAK,SAAA,CAAUC,CAAO,CAAA,CAC5B,SAAA,CAAW,IACb,CAAC,CAAA,CAAE,KAAA,CAAM,IAAM,CAEf,CAAC,EACH,CAEA,OAAA,EAAgB,CACV,KAAK,KAAA,GACP,aAAA,CAAc,IAAA,CAAK,KAAK,CAAA,CACxB,IAAA,CAAK,KAAA,CAAQ,IAAA,CAAA,CAEX,IAAA,CAAK,kBAAA,EAAsBL,CAAAA,EAAK,mBAAA,EAClCA,CAAAA,CAAI,mBAAA,CAAoB,kBAAA,CAAoB,IAAA,CAAK,kBAAkB,CAAA,CAErE,IAAA,CAAK,KAAA,GACP,CACF,CAAA,CC1GA,IAAMM,CAAAA,CAAmB,kCAAA,CAIzB,SAASC,CAAAA,EAA8B,CACrC,GAAI,CACF,IAAMR,CAAAA,CAAI,UAAA,CACJS,CAAAA,CAAMT,CAAAA,CAAE,SAAA,CAGd,GAAIS,CAAAA,EAAOA,CAAAA,CAAI,OAAA,GAAY,aAAA,CACzB,OAAO,cAAA,CAET,IAAMC,CAAAA,CAAMV,CAAAA,CAAE,MAAA,CACd,GAAIU,CAAAA,EAAO,OAAOA,CAAAA,CAAI,QAAA,CAAa,GAAA,CACjC,OAAO,SAAA,CAGT,GADaV,CAAAA,CAAE,OAAA,EACL,QAAA,EAAU,IAAA,CAClB,OAAO,MAAA,CAET,GAAI,OAAO,UAAA,CAAe,GAAA,CACxB,OAAO,MAEX,CAAA,KAAQ,CAER,CACA,OAAO,SACT,CAEA,IAAMW,CAAAA,CAAeH,CAAAA,EAAe,CAE9BI,CAAAA,CAAQ,UAAA,CAAuC,OAAA,CAG/CC,CAAAA,CAAY,OAAOD,CAAAA,EAAM,MAAA,EAAQ,MAAA,EAAW,UAAA,CAElD,SAASE,CAAAA,EAAyB,CAChC,OAAID,CAAAA,CAEKD,CAAAA,CAAM,MAAA,CAAQ,MAAA,EAAQ,CAE3B,OAAO,WAAA,CAAgB,GAAA,CAClB,WAAA,CAAY,GAAA,EAAI,CAElB,IAAA,CAAK,GAAA,EACd,CAEA,SAASG,CAAAA,CAAUC,CAAAA,CAAgC,CACjD,IAAMC,CAAAA,CAAMH,CAAAA,EAAM,CAClB,OAAI,OAAOE,CAAAA,EAAU,QAAA,EAAY,OAAOC,CAAAA,EAAQ,QAAA,CAEvC,MAAA,CAAA,CAAQA,CAAAA,CAAMD,GAAS,KAAK,CAAA,CAG9B,IAAA,CAAK,KAAA,CAAA,CAAQC,CAAAA,CAAkBD,CAAAA,EAAoB,GAAI,CAChE,CA6DA,IAAME,CAAAA,CAAN,KAAuC,CACpB,MAAA,CACA,WAAA,CACA,OAAA,CACA,WAAA,CACT,QAAA,CAAuC,IAAA,CACvC,iBAAA,CAAuC,EAAC,CAC/B,eAAA,CAAmC,IAAI,GAAA,CAChD,WAAA,CAAkC,IAAA,CACzB,aAAA,CACA,qBAAA,CACA,kBAAA,CAER,KAET,WAAA,CAAYf,CAAAA,CAAyB,CACnC,IAAA,CAAK,MAAA,CAASA,CAAAA,CAAQ,MAAA,CACtB,IAAA,CAAK,WAAA,CAAcA,CAAAA,CAAQ,WAAA,CAC3B,IAAA,CAAK,OAAA,CAAUA,CAAAA,CAAQ,OAAA,EAAWI,CAAAA,CAClC,IAAA,CAAK,aAAA,CAAgBJ,CAAAA,CAAQ,MAAA,EAAQ,OAAA,EAAW,IAAA,CAChD,IAAA,CAAK,qBAAA,CAAwBA,CAAAA,CAAQ,MAAA,EAAQ,eAAA,EAAmB,GAAA,CAChE,IAAA,CAAK,kBAAA,CAAqBA,EAAQ,MAAA,EAAQ,YAAA,EAAgB,GAAA,CAC1D,IAAA,CAAK,WAAA,CAAc,IAAA,CAAK,IAAA,EAAK,CAE7B,IAAA,CAAK,IAAA,CAAO,CACV,SAAA,CAAW,IAAA,CAAK,aAAA,CAAc,IAAA,CAAK,IAAI,CAAA,CACvC,GAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA,CAC3B,QAAA,CAAU,IAAA,CAAK,YAAA,CAAa,IAAA,CAAK,IAAI,CAAA,CACrC,KAAA,CAAO,KAAK,SAAA,CAAU,IAAA,CAAK,IAAI,CACjC,CAAA,CAEA,IAAMgB,CAAAA,CAAiBhB,CAAAA,CAAQ,OAAA,EAAS,OAAA,EAAW,IAAA,CAC7CiB,CAAAA,CAAoBjB,CAAAA,CAAQ,OAAA,EAAS,UAAA,EAAc,GAAA,CAErDgB,CAAAA,EACF,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,IAAM,CAC1B,WAAA,CAAY,SAAY,CACtB,GAAI,CACF,IAAME,CAAAA,CAAkB,IAAA,CAAK,UAAU,OAAA,CAEvC,GADA,MAAM,IAAA,CAAK,OAAA,EAAQ,CACf,IAAA,CAAK,QAAA,EAAY,IAAA,CAAK,QAAA,CAAS,OAAA,GAAYA,CAAAA,CAC7C,IAAA,IAAWC,CAAAA,IAAM,IAAA,CAAK,eAAA,CACpBA,CAAAA,GAGN,CAAA,MAASC,CAAAA,CAAO,CACd,OAAA,CAAQ,IAAA,CAAK,iCAAA,CAAmCA,CAAK,EACvD,CACF,CAAA,CAAGH,CAAiB,EACtB,CAAC,EAEL,CAEA,MAAc,IAAA,EAAsB,CAClC,IAAMI,CAAAA,CAAe,MAAM,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,SAAA,CAAA,CAAa,CAC3D,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CAAE,cAAA,CAAgB,kBAAmB,CAAA,CAC9C,IAAA,CAAM,IAAA,CAAK,SAAA,CAAU,CAAE,MAAA,CAAQ,IAAA,CAAK,MAAO,CAAC,CAC9C,CAAC,CAAA,CAED,GAAI,CAACA,CAAAA,CAAa,EAAA,CAAI,CACpB,IAAMD,CAAAA,CAAQ,MAAMC,CAAAA,CAAa,IAAA,EAAK,CAAE,KAAA,CAAM,KAAO,EAAC,CAAE,CAAA,CACxD,MAAM,IAAI,KAAA,CACR,CAAA,gCAAA,EAAoCD,CAAAA,CAA6B,KAAA,EAASC,CAAAA,CAAa,UAAU,CAAA,CACnG,CACF,CAEA,IAAMC,CAAAA,CAAY,MAAMD,CAAAA,CAAa,IAAA,EAAK,CAK1C,GAAI,CAACC,CAAAA,CAAS,KAAA,CACZ,MAAM,IAAI,KAAA,CACR,CAAA,2BAAA,EAA8BA,CAAAA,CAAS,KAAA,EAAS,eAAe,CAAA,CACjE,CAAA,CAGF,IAAMC,CAAAA,CAAmB,MAAM,KAAA,CAC7B,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,0BAAA,EAA6B,kBAAA,CAAmB,IAAA,CAAK,WAAW,CAAC,CAAA,CAAA,CAChF,CAAE,QAAS,CAAE,aAAA,CAAe,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAG,CAAE,CACxD,CAAA,CAEA,GAAI,CAACA,CAAAA,CAAiB,EAAA,CAAI,CACxB,IAAMH,CAAAA,CAAQ,MAAMG,CAAAA,CAAiB,IAAA,EAAK,CAAE,KAAA,CAAM,KAAO,EAAC,CAAE,CAAA,CAC5D,MAAM,IAAI,KAAA,CACR,CAAA,oCAAA,EAAwCH,CAAAA,CAA6B,OAASG,CAAAA,CAAiB,UAAU,CAAA,CAC3G,CACF,CAEA,IAAA,CAAK,QAAA,CAAY,MAAMA,CAAAA,CAAiB,IAAA,EAAK,CAEzC,IAAA,CAAK,aAAA,EAAiB,IAAA,CAAK,QAAA,CAAS,IAAA,GACtC,IAAA,CAAK,WAAA,CAAc,IAAIxB,CAAAA,CAAY,CACjC,OAAA,CAAS,IAAA,CAAK,OAAA,CACd,MAAA,CAAQ,IAAA,CAAK,MAAA,CACb,IAAA,CAAM,CACJ,SAAA,CAAW,KAAK,QAAA,CAAS,IAAA,CAAK,SAAA,CAC9B,cAAA,CAAgB,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,cAAA,CACnC,aAAA,CAAe,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,aAAA,CAClC,WAAA,CAAaS,CACf,CAAA,CACA,eAAA,CAAiB,IAAA,CAAK,qBAAA,CACtB,YAAA,CAAc,IAAA,CAAK,kBACrB,CAAC,CAAA,EAEL,CAEQ,WAAA,EAAmC,CACzC,GAAI,CAAC,IAAA,CAAK,SACR,MAAM,IAAI,KAAA,CACR,6DACF,CAAA,CAEF,OAAO,IAAA,CAAK,QACd,CAEQ,YAAA,CAAaR,CAAAA,CAEC,CACpB,IAAMwB,CAAAA,CAA4B,EAAC,CAC7BC,CAAAA,CAAW,IAAI,GAAA,CAAI,CACvB,GAAG,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,iBAAiB,CAAA,CACrC,GAAG,MAAA,CAAO,IAAA,CAAKzB,CAAAA,EAAS,SAAW,EAAE,CACvC,CAAC,CAAA,CACD,IAAA,IAAW0B,CAAAA,IAAQD,CAAAA,CACjBD,CAAAA,CAAOE,CAAI,CAAA,CAAI,CACb,GAAG,IAAA,CAAK,iBAAA,CAAkBA,CAAI,CAAA,CAC9B,GAAG1B,CAAAA,EAAS,OAAA,GAAU0B,CAAI,CAC5B,CAAA,CAEF,OAAOF,CACT,CAEQ,QAAA,CAASrC,CAAAA,CAAa3B,CAAAA,CAAqC,CACjE,IAAMmE,CAAAA,CAAW,IAAA,CAAK,WAAA,EAAY,CAClC,GAAI,CAACA,CAAAA,CAAS,KAAA,CACZ,OAEF,IAAMrC,CAAAA,CAAOqC,CAAAA,CAAS,KAAA,CAAMxC,CAAG,CAAA,CAC/B,GAAI,CAACG,CAAAA,CAAM,CACT,IAAA,CAAK,UAAA,CAAW,CACd,OAAA,CAASH,CAAAA,CACT,YAAA,CAAc,MAAA,CACd,KAAA,CAAO,MAAA,CACP,MAAA,CAAQ,gBAAA,CACR,QAAA3B,CAAAA,CACA,iBAAA,CAAmBmE,CAAAA,CAAS,OAC9B,CAAC,CAAA,CACD,MACF,CAEA,IAAMC,CAAAA,CAAYjB,CAAAA,EAAM,CAEpBkB,CAAAA,CACJ,GAAI,CACFA,CAAAA,CAAStC,CAAAA,CAAaD,CAAAA,CAAM9B,CAAAA,CAASmE,CAAAA,CAAS,QAAA,EAAY,EAAE,EAC9D,CAAA,MAASG,CAAAA,CAAK,CAEZD,CAAAA,CAAS,CACP,KAAA,CAAO,OACP,YAAA,CAAc,MAAA,CACd,MAAA,CAAQ,OAAA,CACR,WAAA,CALkBC,CAAAA,YAAe,KAAA,CAAQA,CAAAA,CAAI,OAAA,CAAU,MAAA,CAAOA,CAAG,CAMnE,EACF,CAEA,IAAMC,CAAAA,CAAuBnB,CAAAA,CAAUgB,CAAS,CAAA,CAEhD,OAAA,IAAA,CAAK,UAAA,CAAW,CACd,OAAA,CAASzC,CAAAA,CACT,YAAA,CAAc0C,CAAAA,CAAO,YAAA,CACrB,KAAA,CAAOA,CAAAA,CAAO,KAAA,CACd,OAAQA,CAAAA,CAAO,MAAA,CACf,OAAA,CAAArE,CAAAA,CACA,iBAAA,CAAmBqE,CAAAA,CAAO,iBAAA,CAC1B,iBAAA,CAAmBF,CAAAA,CAAS,OAAA,CAC5B,WAAA,CAAaE,CAAAA,CAAO,WAAA,CACpB,oBAAA,CAAAE,CACF,CAAC,CAAA,CAEMF,CAAAA,CAAO,KAChB,CAEQ,UAAA,CAAWG,CAAAA,CAUV,CACP,GAAI,CAAC,IAAA,CAAK,WAAA,CACR,OAEF,GAAM,CAAE,QAAAxE,CAAQ,CAAA,CAAIwE,CAAAA,CACdC,CAAAA,CAAe,MAAA,CAAO,IAAA,CAAKzE,CAAO,CAAA,CAClC0E,CAAAA,CAAwC,EAAC,CAC/C,IAAA,IAAWR,CAAAA,IAAQO,CAAAA,CACjBC,CAAAA,CAAYR,CAAI,CAAA,CAAI,MAAA,CAAO,IAAA,CAAKlE,CAAAA,CAAQkE,CAAI,CAAA,EAAK,EAAE,CAAA,CAGrD,IAAMS,CAAAA,CACJF,CAAAA,CAAa,MAAA,GAAW,CAAA,EACxBA,EAAa,KAAA,CACVP,CAAAA,EAAS,MAAA,CAAO,IAAA,CAAKlE,CAAAA,CAAQkE,CAAI,CAAA,EAAK,EAAE,CAAA,CAAE,MAAA,GAAW,CACxD,CAAA,CAEF,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,CACpB,OAAA,CAASM,CAAAA,CAAO,OAAA,CAChB,YAAA,CAAcA,CAAAA,CAAO,YAAA,CACrB,KAAA,CAAOA,CAAAA,CAAO,KAAA,CACd,MAAA,CAAQA,CAAAA,CAAO,MAAA,CACf,YAAA,CAAAC,EACA,WAAA,CAAAC,CAAAA,CACA,SAAA,CAAW,IAAA,CAAK,GAAA,EAAI,CACpB,iBAAA,CAAmBF,CAAAA,CAAO,iBAAA,CAC1B,iBAAA,CAAmBA,CAAAA,CAAO,iBAAA,CAC1B,WAAA,CAAaA,CAAAA,CAAO,WAAA,CACpB,oBAAA,CAAsBA,CAAAA,CAAO,oBAAA,CAC7B,WAAA,CAAAG,CACF,CAAC,EACH,CAEA,MAAM,KAAA,EAAuB,CAC3B,MAAM,IAAA,CAAK,YACb,CAEA,SAAmB,CACjB,OAAO,IAAA,CAAK,QAAA,GAAa,IAC3B,CAEA,MAAM,SAAA,CAAUhD,CAAAA,CAAaa,CAAAA,CAA8C,CACzE,MAAM,IAAA,CAAK,WAAA,CACX,IAAMxB,CAAAA,CAAQ,IAAA,CAAK,QAAA,CAASW,CAAAA,CAAK,IAAA,CAAK,YAAA,CAAaa,CAAO,CAAC,CAAA,CAC3D,OAAO,OAAOxB,CAAAA,EAAU,SAAA,CAAYA,CAAAA,CAAQ,KAC9C,CAEA,MAAM,GAAA,CAAOW,CAAAA,CAAaa,CAAAA,CAAqC,CAC7D,MAAM,IAAA,CAAK,WAAA,CACX,IAAMxB,CAAAA,CAAQ,IAAA,CAAK,QAAA,CAASW,CAAAA,CAAK,IAAA,CAAK,YAAA,CAAaa,CAAO,CAAC,CAAA,CAC3D,OAA8BxB,CAAAA,EAE1BwB,CAAAA,CAAQ,QACd,CAEQ,aAAA,CAAcb,CAAAA,CAAaa,CAAAA,CAAqC,CACtE,IAAMxB,CAAAA,CAAQ,IAAA,CAAK,SAASW,CAAAA,CAAK,IAAA,CAAK,YAAA,CAAaa,CAAO,CAAC,CAAA,CAC3D,OAAO,OAAOxB,CAAAA,EAAU,SAAA,CAAYA,CAAAA,CAAQ,KAC9C,CAEQ,OAAA,CAAWW,CAAAA,CAAaa,CAAAA,CAA4B,CAC1D,IAAMxB,CAAAA,CAAQ,IAAA,CAAK,QAAA,CAASW,CAAAA,CAAK,IAAA,CAAK,YAAA,CAAaa,CAAO,CAAC,CAAA,CAC3D,OAA8BxB,CAAAA,EAE1BwB,CAAAA,CAAQ,QACd,CAEQ,YAAA,CACNb,CAAAA,CACAa,CAAAA,CACY,CACZ,IAAM2B,CAAAA,CAAW,IAAA,CAAK,WAAA,EAAY,CAC5BnE,CAAAA,CAAU,IAAA,CAAK,YAAA,CAAawC,CAAO,CAAA,CAEzC,GAAI,CAAC2B,CAAAA,CAAS,KAAA,CACZ,OAAO,CACL,KAAA,CAAO,MAAA,CACP,YAAA,CAAc,MAAA,CACd,MAAA,CAAQ,gBAAA,CACR,iBAAA,CAAmBA,CAAAA,CAAS,OAC9B,EAGF,IAAMrC,CAAAA,CAAOqC,CAAAA,CAAS,KAAA,CAAMxC,CAAG,CAAA,CAC/B,GAAI,CAACG,CAAAA,CACH,OAAO,CACL,KAAA,CAAO,MAAA,CACP,YAAA,CAAc,MAAA,CACd,MAAA,CAAQ,gBAAA,CACR,iBAAA,CAAmBqC,CAAAA,CAAS,OAC9B,CAAA,CAGF,IAAMC,CAAAA,CAAYjB,CAAAA,EAAM,CAEpBkB,CAAAA,CACJ,GAAI,CACFA,CAAAA,CAAStC,CAAAA,CAAaD,EAAM9B,CAAAA,CAASmE,CAAAA,CAAS,QAAA,EAAY,EAAE,EAC9D,CAAA,MAASG,CAAAA,CAAK,CAEZD,CAAAA,CAAS,CACP,KAAA,CAAO,MAAA,CACP,YAAA,CAAc,MAAA,CACd,MAAA,CAAQ,OAAA,CACR,WAAA,CALkBC,CAAAA,YAAe,KAAA,CAAQA,CAAAA,CAAI,OAAA,CAAU,MAAA,CAAOA,CAAG,CAMnE,EACF,CAEA,OAAO,CACL,KAAA,CAAOD,EAAO,KAAA,CACd,YAAA,CAAcA,CAAAA,CAAO,YAAA,CACrB,MAAA,CAAQA,CAAAA,CAAO,MAAA,CACf,iBAAA,CAAmBA,CAAAA,CAAO,iBAAA,CAC1B,WAAA,CAAaA,CAAAA,CAAO,WAAA,CACpB,oBAAA,CAAsBjB,CAAAA,CAAUgB,CAAS,CAAA,CACzC,iBAAA,CAAmBD,CAAAA,CAAS,OAC9B,CACF,CAEQ,SAAA,CACNxC,CAAAA,CACAiD,CAAAA,CACA5E,CAAAA,CACM,CACN,IAAA,CAAK,UAAA,CAAW,CACd,QAAS2B,CAAAA,CACT,YAAA,CAAciD,CAAAA,CAAO,YAAA,CACrB,KAAA,CAAOA,CAAAA,CAAO,KAAA,CACd,MAAA,CAAQA,CAAAA,CAAO,MAAA,CACf,OAAA,CAAS,IAAA,CAAK,YAAA,CAAa,CAAE,OAAA,CAAA5E,CAAQ,CAAC,CAAA,CACtC,iBAAA,CAAmB4E,CAAAA,CAAO,iBAAA,CAC1B,iBAAA,CAAmBA,CAAAA,CAAO,iBAAA,CAC1B,WAAA,CAAaA,CAAAA,CAAO,WAAA,CACpB,oBAAA,CAAsBA,CAAAA,CAAO,oBAC/B,CAAC,EACH,CAEA,QAAA,CAAS5E,CAAAA,CAAkC,CACzC,IAAA,CAAK,iBAAA,CAAoB,CAAE,GAAGA,CAAQ,EACxC,CAEA,KAAA,EAAc,CACZ,IAAA,CAAK,iBAAA,CAAoB,GAC3B,CAEA,MAAM,OAAA,EAAyB,CAC7B,IAAM6E,CAAAA,CAAW,MAAM,KAAA,CACrB,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,0BAAA,EAA6B,mBAAmB,IAAA,CAAK,WAAW,CAAC,CAAA,CAAA,CAChF,CAAE,OAAA,CAAS,CAAE,aAAA,CAAe,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAG,CAAE,CACxD,CAAA,CAEA,GAAI,CAACA,CAAAA,CAAS,EAAA,CAAI,CAChB,IAAMjB,CAAAA,CAAQ,MAAMiB,CAAAA,CAAS,IAAA,EAAK,CAAE,KAAA,CAAM,KAAO,EAAC,CAAE,EACpD,MAAM,IAAI,KAAA,CACR,CAAA,6BAAA,EAAiCjB,CAAAA,CAA6B,KAAA,EAASiB,CAAAA,CAAS,UAAU,CAAA,CAC5F,CACF,CAEA,IAAA,CAAK,QAAA,CAAY,MAAMA,CAAAA,CAAS,IAAA,GAClC,CAEA,WAAA,EAA0C,CACxC,OAAO,IAAA,CAAK,QACd,CAEA,QAAA,CAASC,CAAAA,CAAkC,CACzC,OAAA,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAIA,CAAQ,CAAA,CAC1B,IAAM,IAAA,CAAK,eAAA,CAAgB,MAAA,CAAOA,CAAQ,CACnD,CAEA,KAAA,EAAc,CACR,IAAA,CAAK,WAAA,GACP,IAAA,CAAK,WAAA,CAAY,OAAA,EAAQ,CACzB,IAAA,CAAK,WAAA,CAAc,IAAA,EAEvB,CACF,CAAA,CAuBO,SAASC,CAAAA,CAAcvC,CAAAA,CAAkC,CAC9D,OAAO,IAAIe,CAAAA,CAAcf,CAAO,CAClC","file":"index.cjs","sourcesContent":["import type {\n EvaluationContext,\n EvaluationResult,\n SnapshotFlag,\n SnapshotRollout,\n SnapshotRuleCondition,\n SnapshotSegment,\n SnapshotTarget,\n SnapshotVariation,\n} from \"./types\";\n\nfunction hashString(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n // biome-ignore lint/suspicious/noBitwiseOperators: intentional hash algorithm using bitwise shift\n hash = (hash << 5) - hash + char;\n // biome-ignore lint/suspicious/noBitwiseOperators: converting to 32-bit integer\n hash |= 0;\n }\n return Math.abs(hash);\n}\n\nfunction getBucketValue(\n flagKey: string,\n context: EvaluationContext,\n rollout: SnapshotRollout\n): number {\n const bucketKey =\n context[rollout.bucketContextKind]?.[rollout.bucketAttributeKey];\n const seed = rollout.seed ?? \"\";\n const hashInput = `${flagKey}:${seed}:${String(bucketKey ?? \"anonymous\")}`;\n return hashString(hashInput) % 100_000;\n}\n\nfunction selectVariationFromRollout(\n rollout: SnapshotRollout,\n bucketValue: number,\n variations: Record<string, SnapshotVariation>\n): SnapshotVariation | undefined {\n let cumulative = 0;\n\n for (const rv of rollout.variations) {\n cumulative += rv.weight;\n if (bucketValue < cumulative) {\n return variations[rv.variationKey];\n }\n }\n\n const lastVariation = rollout.variations.at(-1);\n return lastVariation ? variations[lastVariation.variationKey] : undefined;\n}\n\nfunction evaluateCondition(\n condition: SnapshotRuleCondition,\n context: EvaluationContext\n): boolean {\n const { contextKind, attributeKey, operator, value } = condition;\n const contextValue = context[contextKind]?.[attributeKey];\n\n switch (operator) {\n case \"equals\":\n return contextValue === value;\n\n case \"not_equals\":\n return contextValue !== value;\n\n case \"contains\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.includes(value);\n }\n if (Array.isArray(contextValue)) {\n return contextValue.includes(value);\n }\n return false;\n\n case \"not_contains\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return !contextValue.includes(value);\n }\n if (Array.isArray(contextValue)) {\n return !contextValue.includes(value);\n }\n return true;\n\n case \"starts_with\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.startsWith(value);\n }\n return false;\n\n case \"ends_with\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.endsWith(value);\n }\n return false;\n\n case \"greater_than\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue > value;\n }\n return false;\n\n case \"less_than\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue < value;\n }\n return false;\n\n case \"greater_than_or_equal\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue >= value;\n }\n return false;\n\n case \"less_than_or_equal\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue <= value;\n }\n return false;\n\n case \"in\":\n if (Array.isArray(value)) {\n return value.includes(contextValue);\n }\n return false;\n\n case \"not_in\":\n if (Array.isArray(value)) {\n return !value.includes(contextValue);\n }\n return true;\n\n case \"exists\":\n return contextValue !== undefined && contextValue !== null;\n\n case \"not_exists\":\n return contextValue === undefined || contextValue === null;\n\n default:\n return false;\n }\n}\n\nfunction evaluateConditions(\n conditions: SnapshotRuleCondition[],\n context: EvaluationContext\n): boolean {\n return conditions.every((condition) => evaluateCondition(condition, context));\n}\n\nfunction evaluateSegment(\n segment: SnapshotSegment,\n context: EvaluationContext\n): boolean {\n return evaluateConditions(segment.conditions, context);\n}\n\nfunction evaluateTarget(\n target: SnapshotTarget,\n context: EvaluationContext,\n segments: Record<string, SnapshotSegment>\n): boolean {\n switch (target.type) {\n case \"individual\":\n if (\n target.contextKind &&\n target.attributeKey &&\n target.attributeValue !== undefined\n ) {\n return (\n context[target.contextKind]?.[target.attributeKey] ===\n target.attributeValue\n );\n }\n return false;\n\n case \"rule\":\n if (target.conditions) {\n return evaluateConditions(target.conditions, context);\n }\n return false;\n\n case \"segment\":\n if (target.segmentKey) {\n const segment = segments[target.segmentKey];\n if (segment) {\n return evaluateSegment(segment, context);\n }\n }\n return false;\n\n default:\n return false;\n }\n}\n\ninterface ResolvedVariation {\n variation: SnapshotVariation;\n variationKey: string;\n}\n\nfunction resolveTargetVariation(\n target: SnapshotTarget,\n flagKey: string,\n context: EvaluationContext,\n variations: Record<string, SnapshotVariation>\n): ResolvedVariation | undefined {\n if (target.rollout) {\n const bucketValue = getBucketValue(flagKey, context, target.rollout);\n const variation = selectVariationFromRollout(\n target.rollout,\n bucketValue,\n variations\n );\n if (variation) {\n const key = Object.keys(variations).find(\n (k) => variations[k] === variation\n );\n return key ? { variation, variationKey: key } : undefined;\n }\n return undefined;\n }\n\n if (target.variationKey) {\n const variation = variations[target.variationKey];\n return variation\n ? { variation, variationKey: target.variationKey }\n : undefined;\n }\n\n return undefined;\n}\n\nfunction resolveDefaultVariation(\n flag: SnapshotFlag,\n context: EvaluationContext\n): ResolvedVariation | undefined {\n if (flag.defaultRollout) {\n const bucketValue = getBucketValue(flag.key, context, flag.defaultRollout);\n const variation = selectVariationFromRollout(\n flag.defaultRollout,\n bucketValue,\n flag.variations\n );\n if (variation) {\n const key = Object.keys(flag.variations).find(\n (k) => flag.variations[k] === variation\n );\n return key ? { variation, variationKey: key } : undefined;\n }\n return undefined;\n }\n\n if (flag.defaultVariationKey) {\n const variation = flag.variations[flag.defaultVariationKey];\n return variation\n ? { variation, variationKey: flag.defaultVariationKey }\n : undefined;\n }\n\n return undefined;\n}\n\nexport function evaluateFlag(\n flag: SnapshotFlag,\n context: EvaluationContext,\n segments: Record<string, SnapshotSegment>\n): EvaluationResult {\n if (!flag.enabled) {\n const offVariation = flag.variations[flag.offVariationKey];\n return {\n value: offVariation?.value,\n variationKey: flag.offVariationKey,\n reason: \"FLAG_DISABLED\",\n };\n }\n\n const sortedTargets = [...flag.targets].sort(\n (a, b) => a.sortOrder - b.sortOrder\n );\n\n for (const target of sortedTargets) {\n if (evaluateTarget(target, context, segments)) {\n const resolved = resolveTargetVariation(\n target,\n flag.key,\n context,\n flag.variations\n );\n if (resolved) {\n return {\n value: resolved.variation.value,\n variationKey: resolved.variationKey,\n reason: \"TARGET_MATCH\",\n matchedTargetName: target.name,\n };\n }\n }\n }\n\n const resolved = resolveDefaultVariation(flag, context);\n if (resolved) {\n return {\n value: resolved.variation.value,\n variationKey: resolved.variationKey,\n reason: flag.defaultRollout ? \"DEFAULT_ROLLOUT\" : \"DEFAULT_VARIATION\",\n };\n }\n\n return {\n value: undefined,\n variationKey: undefined,\n reason: \"DEFAULT_VARIATION\",\n };\n}\n","import type { EvaluationBatchPayload, EvaluationEvent } from \"./types\";\n\ndeclare const __SDK_VERSION__: string;\nexport const SDK_VERSION = __SDK_VERSION__;\n\ninterface EventBufferOptions {\n baseUrl: string;\n apiKey: string;\n meta: {\n projectId: string;\n organizationId: string;\n environmentId: string;\n sdkPlatform?: string;\n };\n flushIntervalMs: number;\n maxBatchSize: number;\n}\n\nconst g = globalThis as Record<string, unknown>;\nconst doc = g.document as\n | {\n visibilityState?: string;\n addEventListener?: (event: string, handler: () => void) => void;\n removeEventListener?: (event: string, handler: () => void) => void;\n }\n | undefined;\nexport class EventBuffer {\n private readonly events: EvaluationEvent[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private readonly options: EventBufferOptions;\n private readonly onVisibilityChange: (() => void) | null = null;\n\n constructor(options: EventBufferOptions) {\n this.options = options;\n this.timer = setInterval(() => this.flush(), this.options.flushIntervalMs);\n\n if (doc?.addEventListener) {\n this.onVisibilityChange = () => {\n if (doc.visibilityState === \"hidden\") {\n this.flushBeacon();\n }\n };\n doc.addEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n }\n\n push(event: EvaluationEvent): void {\n this.events.push(event);\n if (this.events.length >= this.options.maxBatchSize) {\n this.flush();\n }\n }\n\n private buildPayload(batch: EvaluationEvent[]): EvaluationBatchPayload {\n return {\n meta: {\n ...this.options.meta,\n sdkVersion: SDK_VERSION,\n },\n events: batch,\n };\n }\n\n flush(): void {\n if (this.events.length === 0) {\n return;\n }\n const batch = this.events.splice(0, this.options.maxBatchSize);\n const payload = this.buildPayload(batch);\n\n fetch(`${this.options.baseUrl}/sdk/evaluations`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.options.apiKey}`,\n },\n body: JSON.stringify(payload),\n }).catch(() => {\n // Fire-and-forget: silently drop failed events to prevent unbounded growth\n });\n }\n\n /**\n * Flush with keepalive flag for reliable delivery during page unload.\n * keepalive fetch survives page navigation like sendBeacon but supports headers.\n */\n private flushBeacon(): void {\n if (this.events.length === 0) {\n return;\n }\n\n const batch = this.events.splice(0, this.options.maxBatchSize);\n const payload = this.buildPayload(batch);\n\n fetch(`${this.options.baseUrl}/sdk/evaluations`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.options.apiKey}`,\n },\n body: JSON.stringify(payload),\n keepalive: true,\n }).catch(() => {\n // Fire-and-forget\n });\n }\n\n destroy(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.onVisibilityChange && doc?.removeEventListener) {\n doc.removeEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n this.flush();\n }\n}\n","import { evaluateFlag } from \"./evaluator\";\nimport { EventBuffer } from \"./event-buffer\";\nimport type {\n EnvironmentSnapshot,\n EvaluationContext,\n EvaluationResult,\n FlagOptions,\n GradualOptions,\n IsEnabledOptions,\n} from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://worker.gradual.so/api/v1\";\n\ntype SdkPlatform = \"browser\" | \"node\" | \"react-native\" | \"edge\" | \"unknown\";\n\nfunction detectPlatform(): SdkPlatform {\n try {\n const g = globalThis as Record<string, unknown>;\n const nav = g.navigator as\n | { product?: string; userAgent?: string }\n | undefined;\n if (nav && nav.product === \"ReactNative\") {\n return \"react-native\";\n }\n const win = g.window as { document?: unknown } | undefined;\n if (win && typeof win.document !== \"undefined\") {\n return \"browser\";\n }\n const proc = g.process as { versions?: { node?: string } } | undefined;\n if (proc?.versions?.node) {\n return \"node\";\n }\n if (typeof globalThis !== \"undefined\") {\n return \"edge\";\n }\n } catch {\n // Ignore detection errors\n }\n return \"unknown\";\n}\n\nconst SDK_PLATFORM = detectPlatform();\n\nconst proc = (globalThis as Record<string, unknown>).process as\n | { hrtime?: { bigint?: () => bigint } }\n | undefined;\nconst hasHrtime = typeof proc?.hrtime?.bigint === \"function\";\n\nfunction nowNs(): bigint | number {\n if (hasHrtime) {\n // biome-ignore lint/style/noNonNullAssertion: guarded by hasHrtime check\n return proc!.hrtime!.bigint!();\n }\n if (typeof performance !== \"undefined\") {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction elapsedUs(start: bigint | number): number {\n const end = nowNs();\n if (typeof start === \"bigint\" && typeof end === \"bigint\") {\n // hrtime bigint: nanoseconds → microseconds\n return Number((end - start) / 1000n);\n }\n // performance.now() ms or Date.now() ms → microseconds\n return Math.round(((end as number) - (start as number)) * 1000);\n}\n\nexport interface Gradual {\n /** Wait for the SDK to be ready (snapshot fetched) */\n ready(): Promise<void>;\n\n /** Check if the SDK is ready for sync access */\n isReady(): boolean;\n\n /** Check if a boolean flag is enabled */\n isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean>;\n\n /** Get a flag value with type inference from fallback */\n get<T>(key: string, options: FlagOptions<T>): Promise<T>;\n\n /** Set persistent user context for all evaluations */\n identify(context: EvaluationContext): void;\n\n /** Clear the identified user context */\n reset(): void;\n\n /** Refresh the snapshot from the server */\n refresh(): Promise<void>;\n\n /** Get the current snapshot (for debugging) */\n getSnapshot(): EnvironmentSnapshot | null;\n\n /** Subscribe to snapshot updates from polling (returns unsubscribe function) */\n onUpdate(callback: () => void): () => void;\n\n /** Flush pending evaluation events and stop the event buffer */\n close(): void;\n\n /** Sync methods (throw if not ready) */\n sync: GradualSync;\n}\n\nexport interface EvalDetail {\n value: unknown;\n variationKey: string | undefined;\n reason: EvaluationResult[\"reason\"];\n matchedTargetName?: string;\n errorDetail?: string;\n evaluationDurationUs?: number;\n flagConfigVersion?: number;\n}\n\nexport interface GradualSync {\n /** Sync version of isEnabled (throws if not ready) */\n isEnabled(key: string, options?: IsEnabledOptions): boolean;\n\n /** Sync version of get (throws if not ready) */\n get<T>(key: string, options: FlagOptions<T>): T;\n\n /** Evaluate a flag without tracking. Use with track() for React-safe evaluation. */\n evaluate(key: string, options?: { context?: EvaluationContext }): EvalDetail;\n\n /** Manually track an evaluation that was produced by evaluate(). */\n track(key: string, detail: EvalDetail, context?: EvaluationContext): void;\n}\n\nclass GradualClient implements Gradual {\n private readonly apiKey: string;\n private readonly environment: string;\n private readonly baseUrl: string;\n private readonly initPromise: Promise<void>;\n private snapshot: EnvironmentSnapshot | null = null;\n private identifiedContext: EvaluationContext = {};\n private readonly updateListeners: Set<() => void> = new Set();\n private eventBuffer: EventBuffer | null = null;\n private readonly eventsEnabled: boolean;\n private readonly eventsFlushIntervalMs: number;\n private readonly eventsMaxBatchSize: number;\n\n readonly sync: GradualSync;\n\n constructor(options: GradualOptions) {\n this.apiKey = options.apiKey;\n this.environment = options.environment;\n this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n this.eventsEnabled = options.events?.enabled ?? true;\n this.eventsFlushIntervalMs = options.events?.flushIntervalMs ?? 30_000;\n this.eventsMaxBatchSize = options.events?.maxBatchSize ?? 100;\n this.initPromise = this.init();\n\n this.sync = {\n isEnabled: this.isEnabledSync.bind(this),\n get: this.getSync.bind(this),\n evaluate: this.evaluateSync.bind(this),\n track: this.trackSync.bind(this),\n };\n\n const pollingEnabled = options.polling?.enabled ?? true;\n const pollingIntervalMs = options.polling?.intervalMs ?? 10_000;\n\n if (pollingEnabled) {\n this.initPromise.then(() => {\n setInterval(async () => {\n try {\n const previousVersion = this.snapshot?.version;\n await this.refresh();\n if (this.snapshot && this.snapshot.version !== previousVersion) {\n for (const cb of this.updateListeners) {\n cb();\n }\n }\n } catch (error) {\n console.warn(\"Gradual: Polling refresh failed\", error);\n }\n }, pollingIntervalMs);\n });\n }\n }\n\n private async init(): Promise<void> {\n const initResponse = await fetch(`${this.baseUrl}/sdk/init`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ apiKey: this.apiKey }),\n });\n\n if (!initResponse.ok) {\n const error = await initResponse.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to initialize - ${(error as { error?: string }).error ?? initResponse.statusText}`\n );\n }\n\n const initData = (await initResponse.json()) as {\n valid: boolean;\n error?: string;\n };\n\n if (!initData.valid) {\n throw new Error(\n `Gradual: Invalid API key - ${initData.error ?? \"Unknown error\"}`\n );\n }\n\n const snapshotResponse = await fetch(\n `${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,\n { headers: { Authorization: `Bearer ${this.apiKey}` } }\n );\n\n if (!snapshotResponse.ok) {\n const error = await snapshotResponse.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to fetch snapshot - ${(error as { error?: string }).error ?? snapshotResponse.statusText}`\n );\n }\n\n this.snapshot = (await snapshotResponse.json()) as EnvironmentSnapshot;\n\n if (this.eventsEnabled && this.snapshot.meta) {\n this.eventBuffer = new EventBuffer({\n baseUrl: this.baseUrl,\n apiKey: this.apiKey,\n meta: {\n projectId: this.snapshot.meta.projectId,\n organizationId: this.snapshot.meta.organizationId,\n environmentId: this.snapshot.meta.environmentId,\n sdkPlatform: SDK_PLATFORM,\n },\n flushIntervalMs: this.eventsFlushIntervalMs,\n maxBatchSize: this.eventsMaxBatchSize,\n });\n }\n }\n\n private ensureReady(): EnvironmentSnapshot {\n if (!this.snapshot) {\n throw new Error(\n \"Gradual: SDK not ready. Use await ready() or async methods.\"\n );\n }\n return this.snapshot;\n }\n\n private mergeContext(options?: {\n context?: EvaluationContext;\n }): EvaluationContext {\n const merged: EvaluationContext = {};\n const allKinds = new Set([\n ...Object.keys(this.identifiedContext),\n ...Object.keys(options?.context ?? {}),\n ]);\n for (const kind of allKinds) {\n merged[kind] = {\n ...this.identifiedContext[kind],\n ...options?.context?.[kind],\n };\n }\n return merged;\n }\n\n private evaluate(key: string, context: EvaluationContext): unknown {\n const snapshot = this.ensureReady();\n if (!snapshot.flags) {\n return undefined;\n }\n const flag = snapshot.flags[key];\n if (!flag) {\n this.trackEvent({\n flagKey: key,\n variationKey: undefined,\n value: undefined,\n reason: \"FLAG_NOT_FOUND\",\n context,\n flagConfigVersion: snapshot.version,\n });\n return undefined;\n }\n\n const startTime = nowNs();\n\n let result: EvaluationResult;\n try {\n result = evaluateFlag(flag, context, snapshot.segments ?? {});\n } catch (err) {\n const errorDetail = err instanceof Error ? err.message : String(err);\n result = {\n value: undefined,\n variationKey: undefined,\n reason: \"ERROR\",\n errorDetail,\n };\n }\n\n const evaluationDurationUs = elapsedUs(startTime);\n\n this.trackEvent({\n flagKey: key,\n variationKey: result.variationKey,\n value: result.value,\n reason: result.reason,\n context,\n matchedTargetName: result.matchedTargetName,\n flagConfigVersion: snapshot.version,\n errorDetail: result.errorDetail,\n evaluationDurationUs,\n });\n\n return result.value;\n }\n\n private trackEvent(params: {\n flagKey: string;\n variationKey: string | undefined;\n value: unknown;\n reason: EvaluationResult[\"reason\"];\n context: EvaluationContext;\n matchedTargetName?: string;\n flagConfigVersion?: number;\n errorDetail?: string;\n evaluationDurationUs?: number;\n }): void {\n if (!this.eventBuffer) {\n return;\n }\n const { context } = params;\n const contextKinds = Object.keys(context);\n const contextKeys: Record<string, string[]> = {};\n for (const kind of contextKinds) {\n contextKeys[kind] = Object.keys(context[kind] ?? {});\n }\n\n const isAnonymous =\n contextKinds.length === 0 ||\n contextKinds.every(\n (kind) => Object.keys(context[kind] ?? {}).length === 0\n );\n\n this.eventBuffer.push({\n flagKey: params.flagKey,\n variationKey: params.variationKey,\n value: params.value,\n reason: params.reason,\n contextKinds,\n contextKeys,\n timestamp: Date.now(),\n matchedTargetName: params.matchedTargetName,\n flagConfigVersion: params.flagConfigVersion,\n errorDetail: params.errorDetail,\n evaluationDurationUs: params.evaluationDurationUs,\n isAnonymous,\n });\n }\n\n async ready(): Promise<void> {\n await this.initPromise;\n }\n\n isReady(): boolean {\n return this.snapshot !== null;\n }\n\n async isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean> {\n await this.initPromise;\n const value = this.evaluate(key, this.mergeContext(options));\n return typeof value === \"boolean\" ? value : false;\n }\n\n async get<T>(key: string, options: FlagOptions<T>): Promise<T> {\n await this.initPromise;\n const value = this.evaluate(key, this.mergeContext(options));\n return value !== undefined && value !== null\n ? (value as T)\n : options.fallback;\n }\n\n private isEnabledSync(key: string, options?: IsEnabledOptions): boolean {\n const value = this.evaluate(key, this.mergeContext(options));\n return typeof value === \"boolean\" ? value : false;\n }\n\n private getSync<T>(key: string, options: FlagOptions<T>): T {\n const value = this.evaluate(key, this.mergeContext(options));\n return value !== undefined && value !== null\n ? (value as T)\n : options.fallback;\n }\n\n private evaluateSync(\n key: string,\n options?: { context?: EvaluationContext }\n ): EvalDetail {\n const snapshot = this.ensureReady();\n const context = this.mergeContext(options);\n\n if (!snapshot.flags) {\n return {\n value: undefined,\n variationKey: undefined,\n reason: \"FLAG_NOT_FOUND\",\n flagConfigVersion: snapshot.version,\n };\n }\n\n const flag = snapshot.flags[key];\n if (!flag) {\n return {\n value: undefined,\n variationKey: undefined,\n reason: \"FLAG_NOT_FOUND\",\n flagConfigVersion: snapshot.version,\n };\n }\n\n const startTime = nowNs();\n\n let result: EvaluationResult;\n try {\n result = evaluateFlag(flag, context, snapshot.segments ?? {});\n } catch (err) {\n const errorDetail = err instanceof Error ? err.message : String(err);\n result = {\n value: undefined,\n variationKey: undefined,\n reason: \"ERROR\",\n errorDetail,\n };\n }\n\n return {\n value: result.value,\n variationKey: result.variationKey,\n reason: result.reason,\n matchedTargetName: result.matchedTargetName,\n errorDetail: result.errorDetail,\n evaluationDurationUs: elapsedUs(startTime),\n flagConfigVersion: snapshot.version,\n };\n }\n\n private trackSync(\n key: string,\n detail: EvalDetail,\n context?: EvaluationContext\n ): void {\n this.trackEvent({\n flagKey: key,\n variationKey: detail.variationKey,\n value: detail.value,\n reason: detail.reason,\n context: this.mergeContext({ context }),\n matchedTargetName: detail.matchedTargetName,\n flagConfigVersion: detail.flagConfigVersion,\n errorDetail: detail.errorDetail,\n evaluationDurationUs: detail.evaluationDurationUs,\n });\n }\n\n identify(context: EvaluationContext): void {\n this.identifiedContext = { ...context };\n }\n\n reset(): void {\n this.identifiedContext = {};\n }\n\n async refresh(): Promise<void> {\n const response = await fetch(\n `${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,\n { headers: { Authorization: `Bearer ${this.apiKey}` } }\n );\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to refresh - ${(error as { error?: string }).error ?? response.statusText}`\n );\n }\n\n this.snapshot = (await response.json()) as EnvironmentSnapshot;\n }\n\n getSnapshot(): EnvironmentSnapshot | null {\n return this.snapshot;\n }\n\n onUpdate(callback: () => void): () => void {\n this.updateListeners.add(callback);\n return () => this.updateListeners.delete(callback);\n }\n\n close(): void {\n if (this.eventBuffer) {\n this.eventBuffer.destroy();\n this.eventBuffer = null;\n }\n }\n}\n\n/**\n * Create a Gradual feature flag client\n *\n * @example\n * ```ts\n * const gradual = createGradual({\n * apiKey: 'gra_xxx',\n * environment: 'production'\n * })\n *\n * // Boolean flags\n * const enabled = await gradual.isEnabled('new-feature')\n *\n * // Typed values (inferred from fallback)\n * const theme = await gradual.get('theme', { fallback: 'dark' })\n *\n * // With user context\n * gradual.identify({ userId: '123', plan: 'pro' })\n * const proFeature = await gradual.isEnabled('pro-feature')\n * ```\n */\nexport function createGradual(options: GradualOptions): Gradual {\n return new GradualClient(options);\n}\n"]}
1
+ {"version":3,"sources":["../src/evaluator.ts","../src/event-buffer.ts","../src/client.ts"],"names":["hashString","str","hash","i","char","getBucketValue","flagKey","context","rollout","bucketKey","seed","hashInput","selectVariationFromRollout","bucketValue","variations","cumulative","matchedRv","rv","variation","evaluateCondition","condition","contextKind","attributeKey","operator","value","contextValue","evaluateConditions","conditions","evaluateSegment","segment","evaluateTarget","target","segments","resolveTargetVariation","resolveDefaultVariation","flag","buildRuleMatchReason","buildRolloutReason","rolloutResult","evaluateFlag","sortedTargets","a","b","resolved","reasons","SDK_VERSION","g","doc","EventBuffer","options","event","batch","payload","DEFAULT_BASE_URL","detectPlatform","nav","win","SDK_PLATFORM","proc","hasHrtime","nowNs","elapsedUs","start","end","GradualClient","pollingEnabled","pollingIntervalMs","previousVersion","cb","error","initResponse","initData","snapshotResponse","merged","allKinds","kind","key","snapshot","startTime","output","err","errorDetail","version","ruleMatch","r","durationUs","params","contextKinds","contextKeys","isAnonymous","result","response","callback","createGradual"],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n EvalOutput,\n EvaluationContext,\n Reason,\n SnapshotFlag,\n SnapshotRollout,\n SnapshotRolloutVariation,\n SnapshotRuleCondition,\n SnapshotSegment,\n SnapshotTarget,\n SnapshotVariation,\n} from \"./types\";\n\nfunction hashString(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n // biome-ignore lint/suspicious/noBitwiseOperators: intentional hash algorithm using bitwise shift\n hash = (hash << 5) - hash + char;\n // biome-ignore lint/suspicious/noBitwiseOperators: converting to 32-bit integer\n hash |= 0;\n }\n return Math.abs(hash);\n}\n\nfunction getBucketValue(\n flagKey: string,\n context: EvaluationContext,\n rollout: SnapshotRollout\n): number {\n const bucketKey =\n context[rollout.bucketContextKind]?.[rollout.bucketAttributeKey];\n const seed = rollout.seed ?? \"\";\n const hashInput = `${flagKey}:${seed}:${String(bucketKey ?? \"anonymous\")}`;\n return hashString(hashInput) % 100_000;\n}\n\ninterface RolloutResult {\n variation: SnapshotVariation;\n variationKey: string;\n matchedWeight: number;\n bucketValue: number;\n}\n\nfunction selectVariationFromRollout(\n rollout: SnapshotRollout,\n bucketValue: number,\n variations: Record<string, SnapshotVariation>\n): RolloutResult | undefined {\n let cumulative = 0;\n let matchedRv: SnapshotRolloutVariation | undefined;\n\n for (const rv of rollout.variations) {\n cumulative += rv.weight;\n if (bucketValue < cumulative) {\n matchedRv = rv;\n break;\n }\n }\n\n if (!matchedRv) {\n matchedRv = rollout.variations.at(-1);\n }\n\n if (!matchedRv) {\n return undefined;\n }\n\n const variation = variations[matchedRv.variationKey];\n if (!variation) {\n return undefined;\n }\n\n return {\n variation,\n variationKey: matchedRv.variationKey,\n matchedWeight: matchedRv.weight,\n bucketValue,\n };\n}\n\nfunction evaluateCondition(\n condition: SnapshotRuleCondition,\n context: EvaluationContext\n): boolean {\n const { contextKind, attributeKey, operator, value } = condition;\n const contextValue = context[contextKind]?.[attributeKey];\n\n switch (operator) {\n case \"equals\":\n return contextValue === value;\n\n case \"not_equals\":\n return contextValue !== value;\n\n case \"contains\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.includes(value);\n }\n if (Array.isArray(contextValue)) {\n return contextValue.includes(value);\n }\n return false;\n\n case \"not_contains\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return !contextValue.includes(value);\n }\n if (Array.isArray(contextValue)) {\n return !contextValue.includes(value);\n }\n return true;\n\n case \"starts_with\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.startsWith(value);\n }\n return false;\n\n case \"ends_with\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.endsWith(value);\n }\n return false;\n\n case \"greater_than\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue > value;\n }\n return false;\n\n case \"less_than\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue < value;\n }\n return false;\n\n case \"greater_than_or_equal\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue >= value;\n }\n return false;\n\n case \"less_than_or_equal\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue <= value;\n }\n return false;\n\n case \"in\":\n if (Array.isArray(value)) {\n return value.includes(contextValue);\n }\n return false;\n\n case \"not_in\":\n if (Array.isArray(value)) {\n return !value.includes(contextValue);\n }\n return true;\n\n case \"exists\":\n return contextValue !== undefined && contextValue !== null;\n\n case \"not_exists\":\n return contextValue === undefined || contextValue === null;\n\n default:\n return false;\n }\n}\n\nfunction evaluateConditions(\n conditions: SnapshotRuleCondition[],\n context: EvaluationContext\n): boolean {\n return conditions.every((condition) => evaluateCondition(condition, context));\n}\n\nfunction evaluateSegment(\n segment: SnapshotSegment,\n context: EvaluationContext\n): boolean {\n return evaluateConditions(segment.conditions, context);\n}\n\nfunction evaluateTarget(\n target: SnapshotTarget,\n context: EvaluationContext,\n segments: Record<string, SnapshotSegment>\n): boolean {\n switch (target.type) {\n case \"individual\":\n if (\n target.contextKind &&\n target.attributeKey &&\n target.attributeValue !== undefined\n ) {\n return (\n context[target.contextKind]?.[target.attributeKey] ===\n target.attributeValue\n );\n }\n return false;\n\n case \"rule\":\n if (target.conditions) {\n return evaluateConditions(target.conditions, context);\n }\n return false;\n\n case \"segment\":\n if (target.segmentKey) {\n const segment = segments[target.segmentKey];\n if (segment) {\n return evaluateSegment(segment, context);\n }\n }\n return false;\n\n default:\n return false;\n }\n}\n\nfunction resolveTargetVariation(\n target: SnapshotTarget,\n flagKey: string,\n context: EvaluationContext,\n variations: Record<string, SnapshotVariation>\n): RolloutResult | undefined {\n if (target.rollout) {\n const bucketValue = getBucketValue(flagKey, context, target.rollout);\n return selectVariationFromRollout(target.rollout, bucketValue, variations);\n }\n\n if (target.variationKey) {\n const variation = variations[target.variationKey];\n if (variation) {\n return {\n variation,\n variationKey: target.variationKey,\n matchedWeight: 100_000,\n bucketValue: 0,\n };\n }\n }\n\n return undefined;\n}\n\nfunction resolveDefaultVariation(\n flag: SnapshotFlag,\n context: EvaluationContext\n): RolloutResult | undefined {\n if (flag.defaultRollout) {\n const bucketValue = getBucketValue(flag.key, context, flag.defaultRollout);\n return selectVariationFromRollout(\n flag.defaultRollout,\n bucketValue,\n flag.variations\n );\n }\n\n if (flag.defaultVariationKey) {\n const variation = flag.variations[flag.defaultVariationKey];\n if (variation) {\n return {\n variation,\n variationKey: flag.defaultVariationKey,\n matchedWeight: 100_000,\n bucketValue: 0,\n };\n }\n }\n\n return undefined;\n}\n\nfunction buildRuleMatchReason(target: SnapshotTarget): Reason {\n return {\n type: \"rule_match\",\n ruleId: target.id ?? \"\",\n ruleName: target.name,\n };\n}\n\nfunction buildRolloutReason(rolloutResult: RolloutResult): Reason {\n return {\n type: \"percentage_rollout\",\n percentage: rolloutResult.matchedWeight / 1000,\n bucket: rolloutResult.bucketValue,\n };\n}\n\nexport function evaluateFlag(\n flag: SnapshotFlag,\n context: EvaluationContext,\n segments: Record<string, SnapshotSegment>\n): EvalOutput {\n if (!flag.enabled) {\n const offVariation = flag.variations[flag.offVariationKey];\n return {\n value: offVariation?.value,\n variationKey: flag.offVariationKey,\n\n reasons: [{ type: \"off\" }],\n };\n }\n\n const sortedTargets = [...flag.targets].sort(\n (a, b) => a.sortOrder - b.sortOrder\n );\n\n for (const target of sortedTargets) {\n if (evaluateTarget(target, context, segments)) {\n const resolved = resolveTargetVariation(\n target,\n flag.key,\n context,\n flag.variations\n );\n if (resolved) {\n const reasons: Reason[] = [buildRuleMatchReason(target)];\n if (target.rollout) {\n reasons.push(buildRolloutReason(resolved));\n }\n\n return {\n value: resolved.variation.value,\n variationKey: resolved.variationKey,\n\n reasons,\n matchedTargetName: target.name,\n };\n }\n }\n }\n\n const resolved = resolveDefaultVariation(flag, context);\n if (resolved) {\n const reasons: Reason[] = [];\n if (flag.defaultRollout) {\n reasons.push(buildRolloutReason(resolved));\n }\n reasons.push({ type: \"default\" });\n\n return {\n value: resolved.variation.value,\n variationKey: resolved.variationKey,\n\n reasons,\n };\n }\n\n return {\n value: undefined,\n variationKey: undefined,\n\n reasons: [{ type: \"default\" }],\n };\n}\n","import type { EvaluationBatchPayload, EvaluationEvent } from \"./types\";\n\ndeclare const __SDK_VERSION__: string;\nexport const SDK_VERSION = __SDK_VERSION__;\n\ninterface EventBufferOptions {\n baseUrl: string;\n apiKey: string;\n meta: {\n projectId: string;\n organizationId: string;\n environmentId: string;\n sdkPlatform?: string;\n };\n flushIntervalMs: number;\n maxBatchSize: number;\n}\n\nconst g = globalThis as Record<string, unknown>;\nconst doc = g.document as\n | {\n visibilityState?: string;\n addEventListener?: (event: string, handler: () => void) => void;\n removeEventListener?: (event: string, handler: () => void) => void;\n }\n | undefined;\nexport class EventBuffer {\n private readonly events: EvaluationEvent[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private readonly options: EventBufferOptions;\n private readonly onVisibilityChange: (() => void) | null = null;\n\n constructor(options: EventBufferOptions) {\n this.options = options;\n this.timer = setInterval(() => this.flush(), this.options.flushIntervalMs);\n\n if (doc?.addEventListener) {\n this.onVisibilityChange = () => {\n if (doc.visibilityState === \"hidden\") {\n this.flushBeacon();\n }\n };\n doc.addEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n }\n\n push(event: EvaluationEvent): void {\n this.events.push(event);\n if (this.events.length >= this.options.maxBatchSize) {\n this.flush();\n }\n }\n\n private buildPayload(batch: EvaluationEvent[]): EvaluationBatchPayload {\n return {\n meta: {\n ...this.options.meta,\n sdkVersion: SDK_VERSION,\n },\n events: batch,\n };\n }\n\n flush(): void {\n if (this.events.length === 0) {\n return;\n }\n const batch = this.events.splice(0, this.options.maxBatchSize);\n const payload = this.buildPayload(batch);\n\n fetch(`${this.options.baseUrl}/sdk/evaluations`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.options.apiKey}`,\n },\n body: JSON.stringify(payload),\n }).catch(() => {\n // Fire-and-forget: silently drop failed events to prevent unbounded growth\n });\n }\n\n /**\n * Flush with keepalive flag for reliable delivery during page unload.\n * keepalive fetch survives page navigation like sendBeacon but supports headers.\n */\n private flushBeacon(): void {\n if (this.events.length === 0) {\n return;\n }\n\n const batch = this.events.splice(0, this.options.maxBatchSize);\n const payload = this.buildPayload(batch);\n\n fetch(`${this.options.baseUrl}/sdk/evaluations`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.options.apiKey}`,\n },\n body: JSON.stringify(payload),\n keepalive: true,\n }).catch(() => {\n // Fire-and-forget\n });\n }\n\n destroy(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.onVisibilityChange && doc?.removeEventListener) {\n doc.removeEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n this.flush();\n }\n}\n","import { evaluateFlag } from \"./evaluator\";\nimport { EventBuffer } from \"./event-buffer\";\nimport type {\n EnvironmentSnapshot,\n EvalOutput,\n EvaluationContext,\n EvaluationResult,\n FlagOptions,\n GradualOptions,\n IsEnabledOptions,\n Reason,\n} from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://worker.gradual.so/api/v1\";\n\ntype SdkPlatform = \"browser\" | \"node\" | \"react-native\" | \"edge\" | \"unknown\";\n\nfunction detectPlatform(): SdkPlatform {\n try {\n const g = globalThis as Record<string, unknown>;\n const nav = g.navigator as\n | { product?: string; userAgent?: string }\n | undefined;\n if (nav && nav.product === \"ReactNative\") {\n return \"react-native\";\n }\n const win = g.window as { document?: unknown } | undefined;\n if (win && typeof win.document !== \"undefined\") {\n return \"browser\";\n }\n const proc = g.process as { versions?: { node?: string } } | undefined;\n if (proc?.versions?.node) {\n return \"node\";\n }\n if (typeof globalThis !== \"undefined\") {\n return \"edge\";\n }\n } catch {\n // Ignore detection errors\n }\n return \"unknown\";\n}\n\nconst SDK_PLATFORM = detectPlatform();\n\nconst proc = (globalThis as Record<string, unknown>).process as\n | { hrtime?: { bigint?: () => bigint } }\n | undefined;\nconst hasHrtime = typeof proc?.hrtime?.bigint === \"function\";\n\nfunction nowNs(): bigint | number {\n if (hasHrtime) {\n // biome-ignore lint/style/noNonNullAssertion: guarded by hasHrtime check\n return proc!.hrtime!.bigint!();\n }\n if (typeof performance !== \"undefined\") {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction elapsedUs(start: bigint | number): number {\n const end = nowNs();\n if (typeof start === \"bigint\" && typeof end === \"bigint\") {\n // hrtime bigint: nanoseconds → microseconds\n return Number((end - start) / 1000n);\n }\n // performance.now() ms or Date.now() ms → microseconds\n return Math.round(((end as number) - (start as number)) * 1000);\n}\n\nexport interface Gradual {\n /** Wait for the SDK to be ready (snapshot fetched) */\n ready(): Promise<void>;\n\n /** Check if the SDK is ready for sync access */\n isReady(): boolean;\n\n /** Check if a boolean flag is enabled */\n isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean>;\n\n /** Get a flag value with type inference from fallback */\n get<T>(key: string, options: FlagOptions<T>): Promise<T>;\n\n /** Evaluate a flag and return the full structured result (also tracks the evaluation) */\n evaluate<T = unknown>(\n key: string,\n options?: { context?: EvaluationContext }\n ): Promise<EvaluationResult<T>>;\n\n /** Set persistent user context for all evaluations */\n identify(context: EvaluationContext): void;\n\n /** Clear the identified user context */\n reset(): void;\n\n /** Refresh the snapshot from the server */\n refresh(): Promise<void>;\n\n /** Get the current snapshot (for debugging) */\n getSnapshot(): EnvironmentSnapshot | null;\n\n /** Subscribe to snapshot updates from polling (returns unsubscribe function) */\n onUpdate(callback: () => void): () => void;\n\n /** Flush pending evaluation events and stop the event buffer */\n close(): void;\n\n /** Sync methods (throw if not ready) */\n sync: GradualSync;\n}\n\nexport interface GradualSync {\n /** Sync version of isEnabled (throws if not ready) */\n isEnabled(key: string, options?: IsEnabledOptions): boolean;\n\n /** Sync version of get (throws if not ready) */\n get<T>(key: string, options: FlagOptions<T>): T;\n\n /** Evaluate a flag without tracking. Use with track() for React-safe evaluation. */\n evaluate<T = unknown>(\n key: string,\n options?: { context?: EvaluationContext }\n ): EvaluationResult<T>;\n\n /** Manually track an evaluation that was produced by evaluate(). */\n track(\n key: string,\n result: EvaluationResult,\n context?: EvaluationContext\n ): void;\n}\n\nclass GradualClient implements Gradual {\n private readonly apiKey: string;\n private readonly environment: string;\n private readonly baseUrl: string;\n private readonly initPromise: Promise<void>;\n private snapshot: EnvironmentSnapshot | null = null;\n private identifiedContext: EvaluationContext = {};\n private readonly updateListeners: Set<() => void> = new Set();\n private eventBuffer: EventBuffer | null = null;\n private readonly eventsEnabled: boolean;\n private readonly eventsFlushIntervalMs: number;\n private readonly eventsMaxBatchSize: number;\n\n readonly sync: GradualSync;\n\n constructor(options: GradualOptions) {\n this.apiKey = options.apiKey;\n this.environment = options.environment;\n this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n this.eventsEnabled = options.events?.enabled ?? true;\n this.eventsFlushIntervalMs = options.events?.flushIntervalMs ?? 30_000;\n this.eventsMaxBatchSize = options.events?.maxBatchSize ?? 100;\n this.initPromise = this.init();\n\n this.sync = {\n isEnabled: this.isEnabledSync.bind(this),\n get: this.getSync.bind(this),\n evaluate: this.evaluateSync.bind(this),\n track: this.trackSync.bind(this),\n };\n\n const pollingEnabled = options.polling?.enabled ?? true;\n const pollingIntervalMs = options.polling?.intervalMs ?? 10_000;\n\n if (pollingEnabled) {\n this.initPromise.then(() => {\n setInterval(async () => {\n try {\n const previousVersion = this.snapshot?.version;\n await this.refresh();\n if (this.snapshot && this.snapshot.version !== previousVersion) {\n for (const cb of this.updateListeners) {\n cb();\n }\n }\n } catch (error) {\n console.warn(\"Gradual: Polling refresh failed\", error);\n }\n }, pollingIntervalMs);\n });\n }\n }\n\n private async init(): Promise<void> {\n const initResponse = await fetch(`${this.baseUrl}/sdk/init`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ apiKey: this.apiKey }),\n });\n\n if (!initResponse.ok) {\n const error = await initResponse.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to initialize - ${(error as { error?: string }).error ?? initResponse.statusText}`\n );\n }\n\n const initData = (await initResponse.json()) as {\n valid: boolean;\n error?: string;\n };\n\n if (!initData.valid) {\n throw new Error(\n `Gradual: Invalid API key - ${initData.error ?? \"Unknown error\"}`\n );\n }\n\n const snapshotResponse = await fetch(\n `${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,\n { headers: { Authorization: `Bearer ${this.apiKey}` } }\n );\n\n if (!snapshotResponse.ok) {\n const error = await snapshotResponse.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to fetch snapshot - ${(error as { error?: string }).error ?? snapshotResponse.statusText}`\n );\n }\n\n this.snapshot = (await snapshotResponse.json()) as EnvironmentSnapshot;\n\n if (this.eventsEnabled && this.snapshot.meta) {\n this.eventBuffer = new EventBuffer({\n baseUrl: this.baseUrl,\n apiKey: this.apiKey,\n meta: {\n projectId: this.snapshot.meta.projectId,\n organizationId: this.snapshot.meta.organizationId,\n environmentId: this.snapshot.meta.environmentId,\n sdkPlatform: SDK_PLATFORM,\n },\n flushIntervalMs: this.eventsFlushIntervalMs,\n maxBatchSize: this.eventsMaxBatchSize,\n });\n }\n }\n\n private ensureReady(): EnvironmentSnapshot {\n if (!this.snapshot) {\n throw new Error(\n \"Gradual: SDK not ready. Use await ready() or async methods.\"\n );\n }\n return this.snapshot;\n }\n\n private mergeContext(options?: {\n context?: EvaluationContext;\n }): EvaluationContext {\n const merged: EvaluationContext = {};\n const allKinds = new Set([\n ...Object.keys(this.identifiedContext),\n ...Object.keys(options?.context ?? {}),\n ]);\n for (const kind of allKinds) {\n merged[kind] = {\n ...this.identifiedContext[kind],\n ...options?.context?.[kind],\n };\n }\n return merged;\n }\n\n private evaluateRaw(\n key: string,\n context: EvaluationContext\n ): {\n output: EvalOutput | null;\n snapshot: EnvironmentSnapshot;\n durationUs: number;\n } {\n const snapshot = this.ensureReady();\n if (!snapshot.flags) {\n return { output: null, snapshot, durationUs: 0 };\n }\n const flag = snapshot.flags[key];\n if (!flag) {\n return { output: null, snapshot, durationUs: 0 };\n }\n\n const startTime = nowNs();\n let output: EvalOutput;\n try {\n output = evaluateFlag(flag, context, snapshot.segments ?? {});\n } catch (err) {\n const errorDetail = err instanceof Error ? err.message : String(err);\n output = {\n value: undefined,\n variationKey: undefined,\n reasons: [{ type: \"error\", detail: errorDetail }],\n errorDetail,\n };\n }\n\n return { output, snapshot, durationUs: elapsedUs(startTime) };\n }\n\n private buildResult<T>(\n key: string,\n output: EvalOutput,\n version: number\n ): EvaluationResult<T> {\n const ruleMatch = output.reasons.find(\n (r): r is Extract<Reason, { type: \"rule_match\" }> =>\n r.type === \"rule_match\"\n );\n\n return {\n key,\n value: output.value as T,\n variationKey: output.variationKey,\n reasons: output.reasons,\n ruleId: ruleMatch?.ruleId,\n version,\n evaluatedAt: new Date().toISOString(),\n };\n }\n\n private evaluateAndTrack(key: string, context: EvaluationContext): unknown {\n const { output, snapshot, durationUs } = this.evaluateRaw(key, context);\n\n if (!output) {\n this.trackEvent({\n flagKey: key,\n variationKey: undefined,\n value: undefined,\n reasons: [{ type: \"error\", detail: \"FLAG_NOT_FOUND\" }],\n context,\n flagConfigVersion: snapshot.version,\n });\n return undefined;\n }\n\n this.trackEvent({\n flagKey: key,\n variationKey: output.variationKey,\n value: output.value,\n reasons: output.reasons,\n context,\n matchedTargetName: output.matchedTargetName,\n flagConfigVersion: snapshot.version,\n errorDetail: output.errorDetail,\n evaluationDurationUs: durationUs,\n });\n\n return output.value;\n }\n\n private trackEvent(params: {\n flagKey: string;\n variationKey: string | undefined;\n value: unknown;\n reasons: Reason[];\n evaluatedAt?: string;\n ruleId?: string;\n context: EvaluationContext;\n matchedTargetName?: string;\n flagConfigVersion?: number;\n errorDetail?: string;\n evaluationDurationUs?: number;\n }): void {\n if (!this.eventBuffer) {\n return;\n }\n const { context } = params;\n const contextKinds = Object.keys(context);\n const contextKeys: Record<string, string[]> = {};\n for (const kind of contextKinds) {\n contextKeys[kind] = Object.keys(context[kind] ?? {});\n }\n\n const isAnonymous =\n contextKinds.length === 0 ||\n contextKinds.every(\n (kind) => Object.keys(context[kind] ?? {}).length === 0\n );\n\n this.eventBuffer.push({\n flagKey: params.flagKey,\n variationKey: params.variationKey,\n value: params.value,\n reasons: params.reasons,\n evaluatedAt: params.evaluatedAt,\n ruleId: params.ruleId,\n contextKinds,\n contextKeys,\n timestamp: Date.now(),\n matchedTargetName: params.matchedTargetName,\n flagConfigVersion: params.flagConfigVersion,\n errorDetail: params.errorDetail,\n evaluationDurationUs: params.evaluationDurationUs,\n isAnonymous,\n });\n }\n\n async ready(): Promise<void> {\n await this.initPromise;\n }\n\n isReady(): boolean {\n return this.snapshot !== null;\n }\n\n async isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean> {\n await this.initPromise;\n const value = this.evaluateAndTrack(key, this.mergeContext(options));\n return typeof value === \"boolean\" ? value : false;\n }\n\n async get<T>(key: string, options: FlagOptions<T>): Promise<T> {\n await this.initPromise;\n const value = this.evaluateAndTrack(key, this.mergeContext(options));\n return value !== undefined && value !== null\n ? (value as T)\n : options.fallback;\n }\n\n async evaluate<T = unknown>(\n key: string,\n options?: { context?: EvaluationContext }\n ): Promise<EvaluationResult<T>> {\n await this.initPromise;\n const context = this.mergeContext(options);\n const { output, snapshot, durationUs } = this.evaluateRaw(key, context);\n\n if (!output) {\n const result: EvaluationResult<T> = {\n key,\n value: undefined as T,\n variationKey: undefined,\n reasons: [{ type: \"error\", detail: \"FLAG_NOT_FOUND\" }],\n version: snapshot.version,\n evaluatedAt: new Date().toISOString(),\n };\n this.trackEvent({\n flagKey: key,\n variationKey: undefined,\n value: undefined,\n reasons: result.reasons,\n evaluatedAt: result.evaluatedAt,\n context,\n flagConfigVersion: snapshot.version,\n });\n return result;\n }\n\n const result = this.buildResult<T>(key, output, snapshot.version);\n\n this.trackEvent({\n flagKey: key,\n variationKey: output.variationKey,\n value: output.value,\n reasons: output.reasons,\n evaluatedAt: result.evaluatedAt,\n ruleId: result.ruleId,\n context,\n matchedTargetName: output.matchedTargetName,\n flagConfigVersion: snapshot.version,\n errorDetail: output.errorDetail,\n evaluationDurationUs: durationUs,\n });\n\n return result;\n }\n\n private isEnabledSync(key: string, options?: IsEnabledOptions): boolean {\n const value = this.evaluateAndTrack(key, this.mergeContext(options));\n return typeof value === \"boolean\" ? value : false;\n }\n\n private getSync<T>(key: string, options: FlagOptions<T>): T {\n const value = this.evaluateAndTrack(key, this.mergeContext(options));\n return value !== undefined && value !== null\n ? (value as T)\n : options.fallback;\n }\n\n private evaluateSync<T = unknown>(\n key: string,\n options?: { context?: EvaluationContext }\n ): EvaluationResult<T> {\n const context = this.mergeContext(options);\n const { output, snapshot } = this.evaluateRaw(key, context);\n\n if (!output) {\n return {\n key,\n value: undefined as T,\n variationKey: undefined,\n reasons: [{ type: \"error\", detail: \"FLAG_NOT_FOUND\" }],\n version: snapshot.version,\n evaluatedAt: new Date().toISOString(),\n };\n }\n\n return this.buildResult<T>(key, output, snapshot.version);\n }\n\n private trackSync(\n key: string,\n result: EvaluationResult,\n context?: EvaluationContext\n ): void {\n const ruleMatch = result.reasons.find(\n (r): r is Extract<Reason, { type: \"rule_match\" }> =>\n r.type === \"rule_match\"\n );\n\n this.trackEvent({\n flagKey: key,\n variationKey: result.variationKey,\n value: result.value,\n reasons: result.reasons,\n evaluatedAt: result.evaluatedAt,\n ruleId: result.ruleId,\n context: this.mergeContext({ context }),\n matchedTargetName: ruleMatch?.ruleName,\n flagConfigVersion: result.version,\n });\n }\n\n identify(context: EvaluationContext): void {\n this.identifiedContext = { ...context };\n }\n\n reset(): void {\n this.identifiedContext = {};\n }\n\n async refresh(): Promise<void> {\n const response = await fetch(\n `${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,\n { headers: { Authorization: `Bearer ${this.apiKey}` } }\n );\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to refresh - ${(error as { error?: string }).error ?? response.statusText}`\n );\n }\n\n this.snapshot = (await response.json()) as EnvironmentSnapshot;\n }\n\n getSnapshot(): EnvironmentSnapshot | null {\n return this.snapshot;\n }\n\n onUpdate(callback: () => void): () => void {\n this.updateListeners.add(callback);\n return () => this.updateListeners.delete(callback);\n }\n\n close(): void {\n if (this.eventBuffer) {\n this.eventBuffer.destroy();\n this.eventBuffer = null;\n }\n }\n}\n\n/**\n * Create a Gradual feature flag client\n *\n * @example\n * ```ts\n * const gradual = createGradual({\n * apiKey: 'gra_xxx',\n * environment: 'production'\n * })\n *\n * // Boolean flags\n * const enabled = await gradual.isEnabled('new-feature')\n *\n * // Typed values (inferred from fallback)\n * const theme = await gradual.get('theme', { fallback: 'dark' })\n *\n * // Full structured result\n * const result = await gradual.evaluate('new-feature')\n * // result.value, result.reasons, result.ruleId, result.version\n *\n * // With user context\n * gradual.identify({ userId: '123', plan: 'pro' })\n * const proFeature = await gradual.isEnabled('pro-feature')\n * ```\n */\nexport function createGradual(options: GradualOptions): Gradual {\n return new GradualClient(options);\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -20,6 +20,7 @@ interface SnapshotRollout {
20
20
  seed?: string;
21
21
  }
22
22
  interface SnapshotTarget {
23
+ id?: string;
23
24
  type: "rule" | "individual" | "segment";
24
25
  sortOrder: number;
25
26
  name?: string;
@@ -78,11 +79,35 @@ interface FlagOptions<T> {
78
79
  interface IsEnabledOptions {
79
80
  context?: EvaluationContext;
80
81
  }
81
- type EvaluationReason = "FLAG_DISABLED" | "TARGET_MATCH" | "DEFAULT_ROLLOUT" | "DEFAULT_VARIATION" | "FLAG_NOT_FOUND" | "ERROR";
82
- interface EvaluationResult {
82
+ type Reason = {
83
+ type: "rule_match";
84
+ ruleId: string;
85
+ ruleName?: string;
86
+ } | {
87
+ type: "percentage_rollout";
88
+ percentage: number;
89
+ bucket: number;
90
+ } | {
91
+ type: "default";
92
+ } | {
93
+ type: "off";
94
+ } | {
95
+ type: "error";
96
+ detail: string;
97
+ };
98
+ interface EvaluationResult<T = unknown> {
99
+ key: string;
100
+ value: T;
101
+ variationKey?: string;
102
+ reasons: Reason[];
103
+ ruleId?: string;
104
+ version: number;
105
+ evaluatedAt: string;
106
+ }
107
+ interface EvalOutput {
83
108
  value: unknown;
84
109
  variationKey: string | undefined;
85
- reason: EvaluationReason;
110
+ reasons: Reason[];
86
111
  matchedTargetName?: string;
87
112
  errorDetail?: string;
88
113
  }
@@ -90,11 +115,13 @@ interface EvaluationEvent {
90
115
  flagKey: string;
91
116
  variationKey: string | undefined;
92
117
  value: unknown;
93
- reason: EvaluationReason;
118
+ reasons: Reason[];
94
119
  contextKinds: string[];
95
120
  contextKeys: Record<string, string[]>;
96
121
  timestamp: number;
122
+ evaluatedAt?: string;
97
123
  matchedTargetName?: string;
124
+ ruleId?: string;
98
125
  flagConfigVersion?: number;
99
126
  errorDetail?: string;
100
127
  evaluationDurationUs?: number;
@@ -125,6 +152,10 @@ interface Gradual {
125
152
  isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean>;
126
153
  /** Get a flag value with type inference from fallback */
127
154
  get<T>(key: string, options: FlagOptions<T>): Promise<T>;
155
+ /** Evaluate a flag and return the full structured result (also tracks the evaluation) */
156
+ evaluate<T = unknown>(key: string, options?: {
157
+ context?: EvaluationContext;
158
+ }): Promise<EvaluationResult<T>>;
128
159
  /** Set persistent user context for all evaluations */
129
160
  identify(context: EvaluationContext): void;
130
161
  /** Clear the identified user context */
@@ -140,26 +171,17 @@ interface Gradual {
140
171
  /** Sync methods (throw if not ready) */
141
172
  sync: GradualSync;
142
173
  }
143
- interface EvalDetail {
144
- value: unknown;
145
- variationKey: string | undefined;
146
- reason: EvaluationResult["reason"];
147
- matchedTargetName?: string;
148
- errorDetail?: string;
149
- evaluationDurationUs?: number;
150
- flagConfigVersion?: number;
151
- }
152
174
  interface GradualSync {
153
175
  /** Sync version of isEnabled (throws if not ready) */
154
176
  isEnabled(key: string, options?: IsEnabledOptions): boolean;
155
177
  /** Sync version of get (throws if not ready) */
156
178
  get<T>(key: string, options: FlagOptions<T>): T;
157
179
  /** Evaluate a flag without tracking. Use with track() for React-safe evaluation. */
158
- evaluate(key: string, options?: {
180
+ evaluate<T = unknown>(key: string, options?: {
159
181
  context?: EvaluationContext;
160
- }): EvalDetail;
182
+ }): EvaluationResult<T>;
161
183
  /** Manually track an evaluation that was produced by evaluate(). */
162
- track(key: string, detail: EvalDetail, context?: EvaluationContext): void;
184
+ track(key: string, result: EvaluationResult, context?: EvaluationContext): void;
163
185
  }
164
186
  /**
165
187
  * Create a Gradual feature flag client
@@ -177,6 +199,10 @@ interface GradualSync {
177
199
  * // Typed values (inferred from fallback)
178
200
  * const theme = await gradual.get('theme', { fallback: 'dark' })
179
201
  *
202
+ * // Full structured result
203
+ * const result = await gradual.evaluate('new-feature')
204
+ * // result.value, result.reasons, result.ruleId, result.version
205
+ *
180
206
  * // With user context
181
207
  * gradual.identify({ userId: '123', plan: 'pro' })
182
208
  * const proFeature = await gradual.isEnabled('pro-feature')
@@ -184,6 +210,6 @@ interface GradualSync {
184
210
  */
185
211
  declare function createGradual(options: GradualOptions): Gradual;
186
212
 
187
- declare function evaluateFlag(flag: SnapshotFlag, context: EvaluationContext, segments: Record<string, SnapshotSegment>): EvaluationResult;
213
+ declare function evaluateFlag(flag: SnapshotFlag, context: EvaluationContext, segments: Record<string, SnapshotSegment>): EvalOutput;
188
214
 
189
- export { type EnvironmentSnapshot, type EvalDetail, type EvaluationBatchPayload, type EvaluationContext, type EvaluationEvent, type EvaluationReason, type EvaluationResult, type EventsOptions, type FlagOptions, type Gradual, type GradualOptions, type GradualSync, type IsEnabledOptions, type PollingOptions, type SnapshotFlag, type SnapshotRollout, type SnapshotRolloutVariation, type SnapshotRuleCondition, type SnapshotSegment, type SnapshotTarget, type SnapshotVariation, type TargetingOperator, createGradual, evaluateFlag };
215
+ export { type EnvironmentSnapshot, type EvalOutput, type EvaluationBatchPayload, type EvaluationContext, type EvaluationEvent, type EvaluationResult, type EventsOptions, type FlagOptions, type Gradual, type GradualOptions, type GradualSync, type IsEnabledOptions, type PollingOptions, type Reason, type SnapshotFlag, type SnapshotRollout, type SnapshotRolloutVariation, type SnapshotRuleCondition, type SnapshotSegment, type SnapshotTarget, type SnapshotVariation, type TargetingOperator, createGradual, evaluateFlag };
package/dist/index.d.ts CHANGED
@@ -20,6 +20,7 @@ interface SnapshotRollout {
20
20
  seed?: string;
21
21
  }
22
22
  interface SnapshotTarget {
23
+ id?: string;
23
24
  type: "rule" | "individual" | "segment";
24
25
  sortOrder: number;
25
26
  name?: string;
@@ -78,11 +79,35 @@ interface FlagOptions<T> {
78
79
  interface IsEnabledOptions {
79
80
  context?: EvaluationContext;
80
81
  }
81
- type EvaluationReason = "FLAG_DISABLED" | "TARGET_MATCH" | "DEFAULT_ROLLOUT" | "DEFAULT_VARIATION" | "FLAG_NOT_FOUND" | "ERROR";
82
- interface EvaluationResult {
82
+ type Reason = {
83
+ type: "rule_match";
84
+ ruleId: string;
85
+ ruleName?: string;
86
+ } | {
87
+ type: "percentage_rollout";
88
+ percentage: number;
89
+ bucket: number;
90
+ } | {
91
+ type: "default";
92
+ } | {
93
+ type: "off";
94
+ } | {
95
+ type: "error";
96
+ detail: string;
97
+ };
98
+ interface EvaluationResult<T = unknown> {
99
+ key: string;
100
+ value: T;
101
+ variationKey?: string;
102
+ reasons: Reason[];
103
+ ruleId?: string;
104
+ version: number;
105
+ evaluatedAt: string;
106
+ }
107
+ interface EvalOutput {
83
108
  value: unknown;
84
109
  variationKey: string | undefined;
85
- reason: EvaluationReason;
110
+ reasons: Reason[];
86
111
  matchedTargetName?: string;
87
112
  errorDetail?: string;
88
113
  }
@@ -90,11 +115,13 @@ interface EvaluationEvent {
90
115
  flagKey: string;
91
116
  variationKey: string | undefined;
92
117
  value: unknown;
93
- reason: EvaluationReason;
118
+ reasons: Reason[];
94
119
  contextKinds: string[];
95
120
  contextKeys: Record<string, string[]>;
96
121
  timestamp: number;
122
+ evaluatedAt?: string;
97
123
  matchedTargetName?: string;
124
+ ruleId?: string;
98
125
  flagConfigVersion?: number;
99
126
  errorDetail?: string;
100
127
  evaluationDurationUs?: number;
@@ -125,6 +152,10 @@ interface Gradual {
125
152
  isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean>;
126
153
  /** Get a flag value with type inference from fallback */
127
154
  get<T>(key: string, options: FlagOptions<T>): Promise<T>;
155
+ /** Evaluate a flag and return the full structured result (also tracks the evaluation) */
156
+ evaluate<T = unknown>(key: string, options?: {
157
+ context?: EvaluationContext;
158
+ }): Promise<EvaluationResult<T>>;
128
159
  /** Set persistent user context for all evaluations */
129
160
  identify(context: EvaluationContext): void;
130
161
  /** Clear the identified user context */
@@ -140,26 +171,17 @@ interface Gradual {
140
171
  /** Sync methods (throw if not ready) */
141
172
  sync: GradualSync;
142
173
  }
143
- interface EvalDetail {
144
- value: unknown;
145
- variationKey: string | undefined;
146
- reason: EvaluationResult["reason"];
147
- matchedTargetName?: string;
148
- errorDetail?: string;
149
- evaluationDurationUs?: number;
150
- flagConfigVersion?: number;
151
- }
152
174
  interface GradualSync {
153
175
  /** Sync version of isEnabled (throws if not ready) */
154
176
  isEnabled(key: string, options?: IsEnabledOptions): boolean;
155
177
  /** Sync version of get (throws if not ready) */
156
178
  get<T>(key: string, options: FlagOptions<T>): T;
157
179
  /** Evaluate a flag without tracking. Use with track() for React-safe evaluation. */
158
- evaluate(key: string, options?: {
180
+ evaluate<T = unknown>(key: string, options?: {
159
181
  context?: EvaluationContext;
160
- }): EvalDetail;
182
+ }): EvaluationResult<T>;
161
183
  /** Manually track an evaluation that was produced by evaluate(). */
162
- track(key: string, detail: EvalDetail, context?: EvaluationContext): void;
184
+ track(key: string, result: EvaluationResult, context?: EvaluationContext): void;
163
185
  }
164
186
  /**
165
187
  * Create a Gradual feature flag client
@@ -177,6 +199,10 @@ interface GradualSync {
177
199
  * // Typed values (inferred from fallback)
178
200
  * const theme = await gradual.get('theme', { fallback: 'dark' })
179
201
  *
202
+ * // Full structured result
203
+ * const result = await gradual.evaluate('new-feature')
204
+ * // result.value, result.reasons, result.ruleId, result.version
205
+ *
180
206
  * // With user context
181
207
  * gradual.identify({ userId: '123', plan: 'pro' })
182
208
  * const proFeature = await gradual.isEnabled('pro-feature')
@@ -184,6 +210,6 @@ interface GradualSync {
184
210
  */
185
211
  declare function createGradual(options: GradualOptions): Gradual;
186
212
 
187
- declare function evaluateFlag(flag: SnapshotFlag, context: EvaluationContext, segments: Record<string, SnapshotSegment>): EvaluationResult;
213
+ declare function evaluateFlag(flag: SnapshotFlag, context: EvaluationContext, segments: Record<string, SnapshotSegment>): EvalOutput;
188
214
 
189
- export { type EnvironmentSnapshot, type EvalDetail, type EvaluationBatchPayload, type EvaluationContext, type EvaluationEvent, type EvaluationReason, type EvaluationResult, type EventsOptions, type FlagOptions, type Gradual, type GradualOptions, type GradualSync, type IsEnabledOptions, type PollingOptions, type SnapshotFlag, type SnapshotRollout, type SnapshotRolloutVariation, type SnapshotRuleCondition, type SnapshotSegment, type SnapshotTarget, type SnapshotVariation, type TargetingOperator, createGradual, evaluateFlag };
215
+ export { type EnvironmentSnapshot, type EvalOutput, type EvaluationBatchPayload, type EvaluationContext, type EvaluationEvent, type EvaluationResult, type EventsOptions, type FlagOptions, type Gradual, type GradualOptions, type GradualSync, type IsEnabledOptions, type PollingOptions, type Reason, type SnapshotFlag, type SnapshotRollout, type SnapshotRolloutVariation, type SnapshotRuleCondition, type SnapshotSegment, type SnapshotTarget, type SnapshotVariation, type TargetingOperator, createGradual, evaluateFlag };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- function E(n){let e=0;for(let t=0;t<n.length;t++){let i=n.charCodeAt(t);e=(e<<5)-e+i,e|=0;}return Math.abs(e)}function f(n,e,t){let i=e[t.bucketContextKind]?.[t.bucketAttributeKey],o=t.seed??"",r=`${n}:${o}:${String(i??"anonymous")}`;return E(r)%1e5}function p(n,e,t){let i=0;for(let r of n.variations)if(i+=r.weight,e<i)return t[r.variationKey];let o=n.variations.at(-1);return o?t[o.variationKey]:void 0}function S(n,e){let{contextKind:t,attributeKey:i,operator:o,value:r}=n,a=e[t]?.[i];switch(o){case "equals":return a===r;case "not_equals":return a!==r;case "contains":return typeof a=="string"&&typeof r=="string"||Array.isArray(a)?a.includes(r):false;case "not_contains":return typeof a=="string"&&typeof r=="string"||Array.isArray(a)?!a.includes(r):true;case "starts_with":return typeof a=="string"&&typeof r=="string"?a.startsWith(r):false;case "ends_with":return typeof a=="string"&&typeof r=="string"?a.endsWith(r):false;case "greater_than":return typeof a=="number"&&typeof r=="number"?a>r:false;case "less_than":return typeof a=="number"&&typeof r=="number"?a<r:false;case "greater_than_or_equal":return typeof a=="number"&&typeof r=="number"?a>=r:false;case "less_than_or_equal":return typeof a=="number"&&typeof r=="number"?a<=r:false;case "in":return Array.isArray(r)?r.includes(a):false;case "not_in":return Array.isArray(r)?!r.includes(a):true;case "exists":return a!=null;case "not_exists":return a==null;default:return false}}function y(n,e){return n.every(t=>S(t,e))}function K(n,e){return y(n.conditions,e)}function x(n,e,t){switch(n.type){case "individual":return n.contextKind&&n.attributeKey&&n.attributeValue!==void 0?e[n.contextKind]?.[n.attributeKey]===n.attributeValue:false;case "rule":return n.conditions?y(n.conditions,e):false;case "segment":if(n.segmentKey){let i=t[n.segmentKey];if(i)return K(i,e)}return false;default:return false}}function C(n,e,t,i){if(n.rollout){let o=f(e,t,n.rollout),r=p(n.rollout,o,i);if(r){let a=Object.keys(i).find(s=>i[s]===r);return a?{variation:r,variationKey:a}:void 0}return}if(n.variationKey){let o=i[n.variationKey];return o?{variation:o,variationKey:n.variationKey}:void 0}}function T(n,e){if(n.defaultRollout){let t=f(n.key,e,n.defaultRollout),i=p(n.defaultRollout,t,n.variations);if(i){let o=Object.keys(n.variations).find(r=>n.variations[r]===i);return o?{variation:i,variationKey:o}:void 0}return}if(n.defaultVariationKey){let t=n.variations[n.defaultVariationKey];return t?{variation:t,variationKey:n.defaultVariationKey}:void 0}}function d(n,e,t){if(!n.enabled)return {value:n.variations[n.offVariationKey]?.value,variationKey:n.offVariationKey,reason:"FLAG_DISABLED"};let i=[...n.targets].sort((r,a)=>r.sortOrder-a.sortOrder);for(let r of i)if(x(r,e,t)){let a=C(r,n.key,e,n.variations);if(a)return {value:a.variation.value,variationKey:a.variationKey,reason:"TARGET_MATCH",matchedTargetName:r.name}}let o=T(n,e);return o?{value:o.variation.value,variationKey:o.variationKey,reason:n.defaultRollout?"DEFAULT_ROLLOUT":"DEFAULT_VARIATION"}:{value:void 0,variationKey:void 0,reason:"DEFAULT_VARIATION"}}var R="0.7.5",k=globalThis,u=k.document,v=class{events=[];timer=null;options;onVisibilityChange=null;constructor(e){this.options=e,this.timer=setInterval(()=>this.flush(),this.options.flushIntervalMs),u?.addEventListener&&(this.onVisibilityChange=()=>{u.visibilityState==="hidden"&&this.flushBeacon();},u.addEventListener("visibilitychange",this.onVisibilityChange));}push(e){this.events.push(e),this.events.length>=this.options.maxBatchSize&&this.flush();}buildPayload(e){return {meta:{...this.options.meta,sdkVersion:R},events:e}}flush(){if(this.events.length===0)return;let e=this.events.splice(0,this.options.maxBatchSize),t=this.buildPayload(e);fetch(`${this.options.baseUrl}/sdk/evaluations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`},body:JSON.stringify(t)}).catch(()=>{});}flushBeacon(){if(this.events.length===0)return;let e=this.events.splice(0,this.options.maxBatchSize),t=this.buildPayload(e);fetch(`${this.options.baseUrl}/sdk/evaluations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`},body:JSON.stringify(t),keepalive:true}).catch(()=>{});}destroy(){this.timer&&(clearInterval(this.timer),this.timer=null),this.onVisibilityChange&&u?.removeEventListener&&u.removeEventListener("visibilitychange",this.onVisibilityChange),this.flush();}};var w="https://worker.gradual.so/api/v1";function O(){try{let n=globalThis,e=n.navigator;if(e&&e.product==="ReactNative")return "react-native";let t=n.window;if(t&&typeof t.document<"u")return "browser";if(n.process?.versions?.node)return "node";if(typeof globalThis<"u")return "edge"}catch{}return "unknown"}var V=O(),m=globalThis.process,D=typeof m?.hrtime?.bigint=="function";function h(){return D?m.hrtime.bigint():typeof performance<"u"?performance.now():Date.now()}function g(n){let e=h();return typeof n=="bigint"&&typeof e=="bigint"?Number((e-n)/1000n):Math.round((e-n)*1e3)}var c=class{apiKey;environment;baseUrl;initPromise;snapshot=null;identifiedContext={};updateListeners=new Set;eventBuffer=null;eventsEnabled;eventsFlushIntervalMs;eventsMaxBatchSize;sync;constructor(e){this.apiKey=e.apiKey,this.environment=e.environment,this.baseUrl=e.baseUrl??w,this.eventsEnabled=e.events?.enabled??true,this.eventsFlushIntervalMs=e.events?.flushIntervalMs??3e4,this.eventsMaxBatchSize=e.events?.maxBatchSize??100,this.initPromise=this.init(),this.sync={isEnabled:this.isEnabledSync.bind(this),get:this.getSync.bind(this),evaluate:this.evaluateSync.bind(this),track:this.trackSync.bind(this)};let t=e.polling?.enabled??true,i=e.polling?.intervalMs??1e4;t&&this.initPromise.then(()=>{setInterval(async()=>{try{let o=this.snapshot?.version;if(await this.refresh(),this.snapshot&&this.snapshot.version!==o)for(let r of this.updateListeners)r();}catch(o){console.warn("Gradual: Polling refresh failed",o);}},i);});}async init(){let e=await fetch(`${this.baseUrl}/sdk/init`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:this.apiKey})});if(!e.ok){let o=await e.json().catch(()=>({}));throw new Error(`Gradual: Failed to initialize - ${o.error??e.statusText}`)}let t=await e.json();if(!t.valid)throw new Error(`Gradual: Invalid API key - ${t.error??"Unknown error"}`);let i=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!i.ok){let o=await i.json().catch(()=>({}));throw new Error(`Gradual: Failed to fetch snapshot - ${o.error??i.statusText}`)}this.snapshot=await i.json(),this.eventsEnabled&&this.snapshot.meta&&(this.eventBuffer=new v({baseUrl:this.baseUrl,apiKey:this.apiKey,meta:{projectId:this.snapshot.meta.projectId,organizationId:this.snapshot.meta.organizationId,environmentId:this.snapshot.meta.environmentId,sdkPlatform:V},flushIntervalMs:this.eventsFlushIntervalMs,maxBatchSize:this.eventsMaxBatchSize}));}ensureReady(){if(!this.snapshot)throw new Error("Gradual: SDK not ready. Use await ready() or async methods.");return this.snapshot}mergeContext(e){let t={},i=new Set([...Object.keys(this.identifiedContext),...Object.keys(e?.context??{})]);for(let o of i)t[o]={...this.identifiedContext[o],...e?.context?.[o]};return t}evaluate(e,t){let i=this.ensureReady();if(!i.flags)return;let o=i.flags[e];if(!o){this.trackEvent({flagKey:e,variationKey:void 0,value:void 0,reason:"FLAG_NOT_FOUND",context:t,flagConfigVersion:i.version});return}let r=h(),a;try{a=d(o,t,i.segments??{});}catch(l){a={value:void 0,variationKey:void 0,reason:"ERROR",errorDetail:l instanceof Error?l.message:String(l)};}let s=g(r);return this.trackEvent({flagKey:e,variationKey:a.variationKey,value:a.value,reason:a.reason,context:t,matchedTargetName:a.matchedTargetName,flagConfigVersion:i.version,errorDetail:a.errorDetail,evaluationDurationUs:s}),a.value}trackEvent(e){if(!this.eventBuffer)return;let{context:t}=e,i=Object.keys(t),o={};for(let a of i)o[a]=Object.keys(t[a]??{});let r=i.length===0||i.every(a=>Object.keys(t[a]??{}).length===0);this.eventBuffer.push({flagKey:e.flagKey,variationKey:e.variationKey,value:e.value,reason:e.reason,contextKinds:i,contextKeys:o,timestamp:Date.now(),matchedTargetName:e.matchedTargetName,flagConfigVersion:e.flagConfigVersion,errorDetail:e.errorDetail,evaluationDurationUs:e.evaluationDurationUs,isAnonymous:r});}async ready(){await this.initPromise;}isReady(){return this.snapshot!==null}async isEnabled(e,t){await this.initPromise;let i=this.evaluate(e,this.mergeContext(t));return typeof i=="boolean"?i:false}async get(e,t){await this.initPromise;let i=this.evaluate(e,this.mergeContext(t));return i??t.fallback}isEnabledSync(e,t){let i=this.evaluate(e,this.mergeContext(t));return typeof i=="boolean"?i:false}getSync(e,t){let i=this.evaluate(e,this.mergeContext(t));return i??t.fallback}evaluateSync(e,t){let i=this.ensureReady(),o=this.mergeContext(t);if(!i.flags)return {value:void 0,variationKey:void 0,reason:"FLAG_NOT_FOUND",flagConfigVersion:i.version};let r=i.flags[e];if(!r)return {value:void 0,variationKey:void 0,reason:"FLAG_NOT_FOUND",flagConfigVersion:i.version};let a=h(),s;try{s=d(r,o,i.segments??{});}catch(l){s={value:void 0,variationKey:void 0,reason:"ERROR",errorDetail:l instanceof Error?l.message:String(l)};}return {value:s.value,variationKey:s.variationKey,reason:s.reason,matchedTargetName:s.matchedTargetName,errorDetail:s.errorDetail,evaluationDurationUs:g(a),flagConfigVersion:i.version}}trackSync(e,t,i){this.trackEvent({flagKey:e,variationKey:t.variationKey,value:t.value,reason:t.reason,context:this.mergeContext({context:i}),matchedTargetName:t.matchedTargetName,flagConfigVersion:t.flagConfigVersion,errorDetail:t.errorDetail,evaluationDurationUs:t.evaluationDurationUs});}identify(e){this.identifiedContext={...e};}reset(){this.identifiedContext={};}async refresh(){let e=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!e.ok){let t=await e.json().catch(()=>({}));throw new Error(`Gradual: Failed to refresh - ${t.error??e.statusText}`)}this.snapshot=await e.json();}getSnapshot(){return this.snapshot}onUpdate(e){return this.updateListeners.add(e),()=>this.updateListeners.delete(e)}close(){this.eventBuffer&&(this.eventBuffer.destroy(),this.eventBuffer=null);}};function _(n){return new c(n)}
2
- export{_ as createGradual,d as evaluateFlag};//# sourceMappingURL=index.js.map
1
+ function b(n){let t=0;for(let e=0;e<n.length;e++){let a=n.charCodeAt(e);t=(t<<5)-t+a,t|=0;}return Math.abs(t)}function f(n,t,e){let a=t[e.bucketContextKind]?.[e.bucketAttributeKey],o=e.seed??"",i=`${n}:${o}:${String(a??"anonymous")}`;return b(i)%1e5}function p(n,t,e){let a=0,o;for(let r of n.variations)if(a+=r.weight,t<a){o=r;break}if(o||(o=n.variations.at(-1)),!o)return;let i=e[o.variationKey];if(i)return {variation:i,variationKey:o.variationKey,matchedWeight:o.weight,bucketValue:t}}function E(n,t){let{contextKind:e,attributeKey:a,operator:o,value:i}=n,r=t[e]?.[a];switch(o){case "equals":return r===i;case "not_equals":return r!==i;case "contains":return typeof r=="string"&&typeof i=="string"||Array.isArray(r)?r.includes(i):false;case "not_contains":return typeof r=="string"&&typeof i=="string"||Array.isArray(r)?!r.includes(i):true;case "starts_with":return typeof r=="string"&&typeof i=="string"?r.startsWith(i):false;case "ends_with":return typeof r=="string"&&typeof i=="string"?r.endsWith(i):false;case "greater_than":return typeof r=="number"&&typeof i=="number"?r>i:false;case "less_than":return typeof r=="number"&&typeof i=="number"?r<i:false;case "greater_than_or_equal":return typeof r=="number"&&typeof i=="number"?r>=i:false;case "less_than_or_equal":return typeof r=="number"&&typeof i=="number"?r<=i:false;case "in":return Array.isArray(i)?i.includes(r):false;case "not_in":return Array.isArray(i)?!i.includes(r):true;case "exists":return r!=null;case "not_exists":return r==null;default:return false}}function y(n,t){return n.every(e=>E(e,t))}function S(n,t){return y(n.conditions,t)}function R(n,t,e){switch(n.type){case "individual":return n.contextKind&&n.attributeKey&&n.attributeValue!==void 0?t[n.contextKind]?.[n.attributeKey]===n.attributeValue:false;case "rule":return n.conditions?y(n.conditions,t):false;case "segment":if(n.segmentKey){let a=e[n.segmentKey];if(a)return S(a,t)}return false;default:return false}}function x(n,t,e,a){if(n.rollout){let o=f(t,e,n.rollout);return p(n.rollout,o,a)}if(n.variationKey){let o=a[n.variationKey];if(o)return {variation:o,variationKey:n.variationKey,matchedWeight:1e5,bucketValue:0}}}function K(n,t){if(n.defaultRollout){let e=f(n.key,t,n.defaultRollout);return p(n.defaultRollout,e,n.variations)}if(n.defaultVariationKey){let e=n.variations[n.defaultVariationKey];if(e)return {variation:e,variationKey:n.defaultVariationKey,matchedWeight:1e5,bucketValue:0}}}function T(n){return {type:"rule_match",ruleId:n.id??"",ruleName:n.name}}function c(n){return {type:"percentage_rollout",percentage:n.matchedWeight/1e3,bucket:n.bucketValue}}function v(n,t,e){if(!n.enabled)return {value:n.variations[n.offVariationKey]?.value,variationKey:n.offVariationKey,reasons:[{type:"off"}]};let a=[...n.targets].sort((i,r)=>i.sortOrder-r.sortOrder);for(let i of a)if(R(i,t,e)){let r=x(i,n.key,t,n.variations);if(r){let s=[T(i)];return i.rollout&&s.push(c(r)),{value:r.variation.value,variationKey:r.variationKey,reasons:s,matchedTargetName:i.name}}}let o=K(n,t);if(o){let i=[];return n.defaultRollout&&i.push(c(o)),i.push({type:"default"}),{value:o.variation.value,variationKey:o.variationKey,reasons:i}}return {value:void 0,variationKey:void 0,reasons:[{type:"default"}]}}var w="0.8.0",k=globalThis,l=k.document,d=class{events=[];timer=null;options;onVisibilityChange=null;constructor(t){this.options=t,this.timer=setInterval(()=>this.flush(),this.options.flushIntervalMs),l?.addEventListener&&(this.onVisibilityChange=()=>{l.visibilityState==="hidden"&&this.flushBeacon();},l.addEventListener("visibilitychange",this.onVisibilityChange));}push(t){this.events.push(t),this.events.length>=this.options.maxBatchSize&&this.flush();}buildPayload(t){return {meta:{...this.options.meta,sdkVersion:w},events:t}}flush(){if(this.events.length===0)return;let t=this.events.splice(0,this.options.maxBatchSize),e=this.buildPayload(t);fetch(`${this.options.baseUrl}/sdk/evaluations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`},body:JSON.stringify(e)}).catch(()=>{});}flushBeacon(){if(this.events.length===0)return;let t=this.events.splice(0,this.options.maxBatchSize),e=this.buildPayload(t);fetch(`${this.options.baseUrl}/sdk/evaluations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`},body:JSON.stringify(e),keepalive:true}).catch(()=>{});}destroy(){this.timer&&(clearInterval(this.timer),this.timer=null),this.onVisibilityChange&&l?.removeEventListener&&l.removeEventListener("visibilitychange",this.onVisibilityChange),this.flush();}};var C="https://worker.gradual.so/api/v1";function O(){try{let n=globalThis,t=n.navigator;if(t&&t.product==="ReactNative")return "react-native";let e=n.window;if(e&&typeof e.document<"u")return "browser";if(n.process?.versions?.node)return "node";if(typeof globalThis<"u")return "edge"}catch{}return "unknown"}var I=O(),g=globalThis.process,V=typeof g?.hrtime?.bigint=="function";function m(){return V?g.hrtime.bigint():typeof performance<"u"?performance.now():Date.now()}function _(n){let t=m();return typeof n=="bigint"&&typeof t=="bigint"?Number((t-n)/1000n):Math.round((t-n)*1e3)}var h=class{apiKey;environment;baseUrl;initPromise;snapshot=null;identifiedContext={};updateListeners=new Set;eventBuffer=null;eventsEnabled;eventsFlushIntervalMs;eventsMaxBatchSize;sync;constructor(t){this.apiKey=t.apiKey,this.environment=t.environment,this.baseUrl=t.baseUrl??C,this.eventsEnabled=t.events?.enabled??true,this.eventsFlushIntervalMs=t.events?.flushIntervalMs??3e4,this.eventsMaxBatchSize=t.events?.maxBatchSize??100,this.initPromise=this.init(),this.sync={isEnabled:this.isEnabledSync.bind(this),get:this.getSync.bind(this),evaluate:this.evaluateSync.bind(this),track:this.trackSync.bind(this)};let e=t.polling?.enabled??true,a=t.polling?.intervalMs??1e4;e&&this.initPromise.then(()=>{setInterval(async()=>{try{let o=this.snapshot?.version;if(await this.refresh(),this.snapshot&&this.snapshot.version!==o)for(let i of this.updateListeners)i();}catch(o){console.warn("Gradual: Polling refresh failed",o);}},a);});}async init(){let t=await fetch(`${this.baseUrl}/sdk/init`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:this.apiKey})});if(!t.ok){let o=await t.json().catch(()=>({}));throw new Error(`Gradual: Failed to initialize - ${o.error??t.statusText}`)}let e=await t.json();if(!e.valid)throw new Error(`Gradual: Invalid API key - ${e.error??"Unknown error"}`);let a=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!a.ok){let o=await a.json().catch(()=>({}));throw new Error(`Gradual: Failed to fetch snapshot - ${o.error??a.statusText}`)}this.snapshot=await a.json(),this.eventsEnabled&&this.snapshot.meta&&(this.eventBuffer=new d({baseUrl:this.baseUrl,apiKey:this.apiKey,meta:{projectId:this.snapshot.meta.projectId,organizationId:this.snapshot.meta.organizationId,environmentId:this.snapshot.meta.environmentId,sdkPlatform:I},flushIntervalMs:this.eventsFlushIntervalMs,maxBatchSize:this.eventsMaxBatchSize}));}ensureReady(){if(!this.snapshot)throw new Error("Gradual: SDK not ready. Use await ready() or async methods.");return this.snapshot}mergeContext(t){let e={},a=new Set([...Object.keys(this.identifiedContext),...Object.keys(t?.context??{})]);for(let o of a)e[o]={...this.identifiedContext[o],...t?.context?.[o]};return e}evaluateRaw(t,e){let a=this.ensureReady();if(!a.flags)return {output:null,snapshot:a,durationUs:0};let o=a.flags[t];if(!o)return {output:null,snapshot:a,durationUs:0};let i=m(),r;try{r=v(o,e,a.segments??{});}catch(s){let u=s instanceof Error?s.message:String(s);r={value:void 0,variationKey:void 0,reasons:[{type:"error",detail:u}],errorDetail:u};}return {output:r,snapshot:a,durationUs:_(i)}}buildResult(t,e,a){let o=e.reasons.find(i=>i.type==="rule_match");return {key:t,value:e.value,variationKey:e.variationKey,reasons:e.reasons,ruleId:o?.ruleId,version:a,evaluatedAt:new Date().toISOString()}}evaluateAndTrack(t,e){let{output:a,snapshot:o,durationUs:i}=this.evaluateRaw(t,e);if(!a){this.trackEvent({flagKey:t,variationKey:void 0,value:void 0,reasons:[{type:"error",detail:"FLAG_NOT_FOUND"}],context:e,flagConfigVersion:o.version});return}return this.trackEvent({flagKey:t,variationKey:a.variationKey,value:a.value,reasons:a.reasons,context:e,matchedTargetName:a.matchedTargetName,flagConfigVersion:o.version,errorDetail:a.errorDetail,evaluationDurationUs:i}),a.value}trackEvent(t){if(!this.eventBuffer)return;let{context:e}=t,a=Object.keys(e),o={};for(let r of a)o[r]=Object.keys(e[r]??{});let i=a.length===0||a.every(r=>Object.keys(e[r]??{}).length===0);this.eventBuffer.push({flagKey:t.flagKey,variationKey:t.variationKey,value:t.value,reasons:t.reasons,evaluatedAt:t.evaluatedAt,ruleId:t.ruleId,contextKinds:a,contextKeys:o,timestamp:Date.now(),matchedTargetName:t.matchedTargetName,flagConfigVersion:t.flagConfigVersion,errorDetail:t.errorDetail,evaluationDurationUs:t.evaluationDurationUs,isAnonymous:i});}async ready(){await this.initPromise;}isReady(){return this.snapshot!==null}async isEnabled(t,e){await this.initPromise;let a=this.evaluateAndTrack(t,this.mergeContext(e));return typeof a=="boolean"?a:false}async get(t,e){await this.initPromise;let a=this.evaluateAndTrack(t,this.mergeContext(e));return a??e.fallback}async evaluate(t,e){await this.initPromise;let a=this.mergeContext(e),{output:o,snapshot:i,durationUs:r}=this.evaluateRaw(t,a);if(!o){let u={key:t,value:void 0,variationKey:void 0,reasons:[{type:"error",detail:"FLAG_NOT_FOUND"}],version:i.version,evaluatedAt:new Date().toISOString()};return this.trackEvent({flagKey:t,variationKey:void 0,value:void 0,reasons:u.reasons,evaluatedAt:u.evaluatedAt,context:a,flagConfigVersion:i.version}),u}let s=this.buildResult(t,o,i.version);return this.trackEvent({flagKey:t,variationKey:o.variationKey,value:o.value,reasons:o.reasons,evaluatedAt:s.evaluatedAt,ruleId:s.ruleId,context:a,matchedTargetName:o.matchedTargetName,flagConfigVersion:i.version,errorDetail:o.errorDetail,evaluationDurationUs:r}),s}isEnabledSync(t,e){let a=this.evaluateAndTrack(t,this.mergeContext(e));return typeof a=="boolean"?a:false}getSync(t,e){let a=this.evaluateAndTrack(t,this.mergeContext(e));return a??e.fallback}evaluateSync(t,e){let a=this.mergeContext(e),{output:o,snapshot:i}=this.evaluateRaw(t,a);return o?this.buildResult(t,o,i.version):{key:t,value:void 0,variationKey:void 0,reasons:[{type:"error",detail:"FLAG_NOT_FOUND"}],version:i.version,evaluatedAt:new Date().toISOString()}}trackSync(t,e,a){let o=e.reasons.find(i=>i.type==="rule_match");this.trackEvent({flagKey:t,variationKey:e.variationKey,value:e.value,reasons:e.reasons,evaluatedAt:e.evaluatedAt,ruleId:e.ruleId,context:this.mergeContext({context:a}),matchedTargetName:o?.ruleName,flagConfigVersion:e.version});}identify(t){this.identifiedContext={...t};}reset(){this.identifiedContext={};}async refresh(){let t=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!t.ok){let e=await t.json().catch(()=>({}));throw new Error(`Gradual: Failed to refresh - ${e.error??t.statusText}`)}this.snapshot=await t.json();}getSnapshot(){return this.snapshot}onUpdate(t){return this.updateListeners.add(t),()=>this.updateListeners.delete(t)}close(){this.eventBuffer&&(this.eventBuffer.destroy(),this.eventBuffer=null);}};function A(n){return new h(n)}
2
+ export{A as createGradual,v as evaluateFlag};//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/evaluator.ts","../src/event-buffer.ts","../src/client.ts"],"names":["hashString","str","hash","i","char","getBucketValue","flagKey","context","rollout","bucketKey","seed","hashInput","selectVariationFromRollout","bucketValue","variations","cumulative","rv","lastVariation","evaluateCondition","condition","contextKind","attributeKey","operator","value","contextValue","evaluateConditions","conditions","evaluateSegment","segment","evaluateTarget","target","segments","resolveTargetVariation","variation","key","k","resolveDefaultVariation","flag","evaluateFlag","sortedTargets","a","b","resolved","SDK_VERSION","g","doc","EventBuffer","options","event","batch","payload","DEFAULT_BASE_URL","detectPlatform","nav","win","SDK_PLATFORM","proc","hasHrtime","nowNs","elapsedUs","start","end","GradualClient","pollingEnabled","pollingIntervalMs","previousVersion","cb","error","initResponse","initData","snapshotResponse","merged","allKinds","kind","snapshot","startTime","result","err","evaluationDurationUs","params","contextKinds","contextKeys","isAnonymous","detail","response","callback","createGradual"],"mappings":"AAWA,SAASA,CAAAA,CAAWC,CAAAA,CAAqB,CACvC,IAAIC,CAAAA,CAAO,CAAA,CACX,IAAA,IAASC,CAAAA,CAAI,CAAA,CAAGA,CAAAA,CAAIF,CAAAA,CAAI,MAAA,CAAQE,CAAAA,EAAAA,CAAK,CACnC,IAAMC,CAAAA,CAAOH,CAAAA,CAAI,UAAA,CAAWE,CAAC,CAAA,CAE7BD,CAAAA,CAAAA,CAAQA,CAAAA,EAAQ,CAAA,EAAKA,CAAAA,CAAOE,CAAAA,CAE5BF,CAAAA,EAAQ,EACV,CACA,OAAO,KAAK,GAAA,CAAIA,CAAI,CACtB,CAEA,SAASG,CAAAA,CACPC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACQ,CACR,IAAMC,CAAAA,CACJF,CAAAA,CAAQC,CAAAA,CAAQ,iBAAiB,CAAA,GAAIA,CAAAA,CAAQ,kBAAkB,CAAA,CAC3DE,CAAAA,CAAOF,CAAAA,CAAQ,IAAA,EAAQ,EAAA,CACvBG,CAAAA,CAAY,CAAA,EAAGL,CAAO,CAAA,CAAA,EAAII,CAAI,CAAA,CAAA,EAAI,MAAA,CAAOD,GAAa,WAAW,CAAC,CAAA,CAAA,CACxE,OAAOT,CAAAA,CAAWW,CAAS,CAAA,CAAI,GACjC,CAEA,SAASC,CAAAA,CACPJ,CAAAA,CACAK,CAAAA,CACAC,CAAAA,CAC+B,CAC/B,IAAIC,CAAAA,CAAa,CAAA,CAEjB,IAAA,IAAWC,CAAAA,IAAMR,CAAAA,CAAQ,UAAA,CAEvB,GADAO,CAAAA,EAAcC,CAAAA,CAAG,MAAA,CACbH,CAAAA,CAAcE,CAAAA,CAChB,OAAOD,CAAAA,CAAWE,EAAG,YAAY,CAAA,CAIrC,IAAMC,CAAAA,CAAgBT,CAAAA,CAAQ,UAAA,CAAW,EAAA,CAAG,EAAE,CAAA,CAC9C,OAAOS,CAAAA,CAAgBH,CAAAA,CAAWG,CAAAA,CAAc,YAAY,CAAA,CAAI,MAClE,CAEA,SAASC,CAAAA,CACPC,CAAAA,CACAZ,CAAAA,CACS,CACT,GAAM,CAAE,WAAA,CAAAa,CAAAA,CAAa,YAAA,CAAAC,CAAAA,CAAc,QAAA,CAAAC,CAAAA,CAAU,MAAAC,CAAM,CAAA,CAAIJ,CAAAA,CACjDK,CAAAA,CAAejB,CAAAA,CAAQa,CAAW,CAAA,GAAIC,CAAY,CAAA,CAExD,OAAQC,CAAAA,EACN,KAAK,QAAA,CACH,OAAOE,CAAAA,GAAiBD,CAAAA,CAE1B,KAAK,YAAA,CACH,OAAOC,CAAAA,GAAiBD,CAAAA,CAE1B,KAAK,UAAA,CAIH,OAHI,OAAOC,CAAAA,EAAiB,QAAA,EAAY,OAAOD,CAAAA,EAAU,UAGrD,KAAA,CAAM,OAAA,CAAQC,CAAY,CAAA,CACrBA,CAAAA,CAAa,QAAA,CAASD,CAAK,CAAA,CAE7B,KAAA,CAET,KAAK,cAAA,CAIH,OAHI,OAAOC,CAAAA,EAAiB,QAAA,EAAY,OAAOD,CAAAA,EAAU,QAAA,EAGrD,KAAA,CAAM,OAAA,CAAQC,CAAY,CAAA,CACrB,CAACA,CAAAA,CAAa,QAAA,CAASD,CAAK,CAAA,CAE9B,IAAA,CAET,KAAK,aAAA,CACH,OAAI,OAAOC,CAAAA,EAAiB,QAAA,EAAY,OAAOD,CAAAA,EAAU,QAAA,CAChDC,CAAAA,CAAa,UAAA,CAAWD,CAAK,CAAA,CAE/B,KAAA,CAET,KAAK,WAAA,CACH,OAAI,OAAOC,CAAAA,EAAiB,QAAA,EAAY,OAAOD,CAAAA,EAAU,QAAA,CAChDC,CAAAA,CAAa,QAAA,CAASD,CAAK,CAAA,CAE7B,KAAA,CAET,KAAK,cAAA,CACH,OAAI,OAAOC,CAAAA,EAAiB,UAAY,OAAOD,CAAAA,EAAU,QAAA,CAChDC,CAAAA,CAAeD,CAAAA,CAEjB,KAAA,CAET,KAAK,WAAA,CACH,OAAI,OAAOC,CAAAA,EAAiB,QAAA,EAAY,OAAOD,CAAAA,EAAU,QAAA,CAChDC,CAAAA,CAAeD,CAAAA,CAEjB,KAAA,CAET,KAAK,uBAAA,CACH,OAAI,OAAOC,CAAAA,EAAiB,QAAA,EAAY,OAAOD,CAAAA,EAAU,QAAA,CAChDC,CAAAA,EAAgBD,CAAAA,CAElB,KAAA,CAET,KAAK,oBAAA,CACH,OAAI,OAAOC,CAAAA,EAAiB,QAAA,EAAY,OAAOD,CAAAA,EAAU,QAAA,CAChDC,CAAAA,EAAgBD,CAAAA,CAElB,KAAA,CAET,KAAK,IAAA,CACH,OAAI,KAAA,CAAM,OAAA,CAAQA,CAAK,CAAA,CACdA,CAAAA,CAAM,QAAA,CAASC,CAAY,CAAA,CAE7B,KAAA,CAET,KAAK,QAAA,CACH,OAAI,KAAA,CAAM,OAAA,CAAQD,CAAK,CAAA,CACd,CAACA,CAAAA,CAAM,QAAA,CAASC,CAAY,CAAA,CAE9B,IAAA,CAET,KAAK,QAAA,CACH,OAAqCA,CAAAA,EAAiB,IAAA,CAExD,KAAK,YAAA,CACH,OAAqCA,CAAAA,EAAiB,IAAA,CAExD,QACE,OAAO,MACX,CACF,CAEA,SAASC,CAAAA,CACPC,CAAAA,CACAnB,CAAAA,CACS,CACT,OAAOmB,CAAAA,CAAW,KAAA,CAAOP,CAAAA,EAAcD,CAAAA,CAAkBC,EAAWZ,CAAO,CAAC,CAC9E,CAEA,SAASoB,CAAAA,CACPC,CAAAA,CACArB,CAAAA,CACS,CACT,OAAOkB,CAAAA,CAAmBG,CAAAA,CAAQ,UAAA,CAAYrB,CAAO,CACvD,CAEA,SAASsB,CAAAA,CACPC,CAAAA,CACAvB,CAAAA,CACAwB,CAAAA,CACS,CACT,OAAQD,CAAAA,CAAO,IAAA,EACb,KAAK,YAAA,CACH,OACEA,CAAAA,CAAO,aACPA,CAAAA,CAAO,YAAA,EACPA,CAAAA,CAAO,cAAA,GAAmB,MAAA,CAGxBvB,CAAAA,CAAQuB,CAAAA,CAAO,WAAW,CAAA,GAAIA,CAAAA,CAAO,YAAY,CAAA,GACjDA,CAAAA,CAAO,cAAA,CAGJ,KAAA,CAET,KAAK,MAAA,CACH,OAAIA,CAAAA,CAAO,UAAA,CACFL,CAAAA,CAAmBK,CAAAA,CAAO,UAAA,CAAYvB,CAAO,CAAA,CAE/C,KAAA,CAET,KAAK,SAAA,CACH,GAAIuB,CAAAA,CAAO,WAAY,CACrB,IAAMF,CAAAA,CAAUG,CAAAA,CAASD,CAAAA,CAAO,UAAU,CAAA,CAC1C,GAAIF,CAAAA,CACF,OAAOD,CAAAA,CAAgBC,CAAAA,CAASrB,CAAO,CAE3C,CACA,OAAO,MAAA,CAET,QACE,OAAO,MACX,CACF,CAOA,SAASyB,CAAAA,CACPF,CAAAA,CACAxB,CAAAA,CACAC,CAAAA,CACAO,CAAAA,CAC+B,CAC/B,GAAIgB,EAAO,OAAA,CAAS,CAClB,IAAMjB,CAAAA,CAAcR,CAAAA,CAAeC,CAAAA,CAASC,CAAAA,CAASuB,CAAAA,CAAO,OAAO,CAAA,CAC7DG,CAAAA,CAAYrB,CAAAA,CAChBkB,CAAAA,CAAO,OAAA,CACPjB,CAAAA,CACAC,CACF,CAAA,CACA,GAAImB,CAAAA,CAAW,CACb,IAAMC,CAAAA,CAAM,MAAA,CAAO,IAAA,CAAKpB,CAAU,CAAA,CAAE,IAAA,CACjCqB,CAAAA,EAAMrB,CAAAA,CAAWqB,CAAC,IAAMF,CAC3B,CAAA,CACA,OAAOC,CAAAA,CAAM,CAAE,SAAA,CAAAD,CAAAA,CAAW,YAAA,CAAcC,CAAI,CAAA,CAAI,MAClD,CACA,MACF,CAEA,GAAIJ,CAAAA,CAAO,YAAA,CAAc,CACvB,IAAMG,CAAAA,CAAYnB,CAAAA,CAAWgB,CAAAA,CAAO,YAAY,CAAA,CAChD,OAAOG,CAAAA,CACH,CAAE,SAAA,CAAAA,CAAAA,CAAW,YAAA,CAAcH,EAAO,YAAa,CAAA,CAC/C,MACN,CAGF,CAEA,SAASM,CAAAA,CACPC,CAAAA,CACA9B,CAAAA,CAC+B,CAC/B,GAAI8B,CAAAA,CAAK,cAAA,CAAgB,CACvB,IAAMxB,CAAAA,CAAcR,CAAAA,CAAegC,CAAAA,CAAK,GAAA,CAAK9B,CAAAA,CAAS8B,CAAAA,CAAK,cAAc,CAAA,CACnEJ,CAAAA,CAAYrB,CAAAA,CAChByB,CAAAA,CAAK,cAAA,CACLxB,CAAAA,CACAwB,CAAAA,CAAK,UACP,EACA,GAAIJ,CAAAA,CAAW,CACb,IAAMC,CAAAA,CAAM,MAAA,CAAO,IAAA,CAAKG,CAAAA,CAAK,UAAU,CAAA,CAAE,IAAA,CACtCF,CAAAA,EAAME,CAAAA,CAAK,UAAA,CAAWF,CAAC,CAAA,GAAMF,CAChC,CAAA,CACA,OAAOC,CAAAA,CAAM,CAAE,SAAA,CAAAD,CAAAA,CAAW,YAAA,CAAcC,CAAI,CAAA,CAAI,MAClD,CACA,MACF,CAEA,GAAIG,CAAAA,CAAK,mBAAA,CAAqB,CAC5B,IAAMJ,CAAAA,CAAYI,CAAAA,CAAK,UAAA,CAAWA,CAAAA,CAAK,mBAAmB,CAAA,CAC1D,OAAOJ,CAAAA,CACH,CAAE,SAAA,CAAAA,CAAAA,CAAW,YAAA,CAAcI,CAAAA,CAAK,mBAAoB,CAAA,CACpD,MACN,CAGF,CAEO,SAASC,CAAAA,CACdD,CAAAA,CACA9B,CAAAA,CACAwB,CAAAA,CACkB,CAClB,GAAI,CAACM,EAAK,OAAA,CAER,OAAO,CACL,KAAA,CAFmBA,CAAAA,CAAK,UAAA,CAAWA,CAAAA,CAAK,eAAe,CAAA,EAElC,KAAA,CACrB,YAAA,CAAcA,CAAAA,CAAK,eAAA,CACnB,MAAA,CAAQ,eACV,CAAA,CAGF,IAAME,CAAAA,CAAgB,CAAC,GAAGF,CAAAA,CAAK,OAAO,CAAA,CAAE,IAAA,CACtC,CAACG,CAAAA,CAAGC,CAAAA,GAAMD,CAAAA,CAAE,SAAA,CAAYC,CAAAA,CAAE,SAC5B,CAAA,CAEA,IAAA,IAAWX,CAAAA,IAAUS,CAAAA,CACnB,GAAIV,CAAAA,CAAeC,CAAAA,CAAQvB,CAAAA,CAASwB,CAAQ,CAAA,CAAG,CAC7C,IAAMW,CAAAA,CAAWV,CAAAA,CACfF,CAAAA,CACAO,CAAAA,CAAK,GAAA,CACL9B,CAAAA,CACA8B,CAAAA,CAAK,UACP,CAAA,CACA,GAAIK,CAAAA,CACF,OAAO,CACL,KAAA,CAAOA,CAAAA,CAAS,SAAA,CAAU,KAAA,CAC1B,YAAA,CAAcA,EAAS,YAAA,CACvB,MAAA,CAAQ,cAAA,CACR,iBAAA,CAAmBZ,CAAAA,CAAO,IAC5B,CAEJ,CAGF,IAAMY,CAAAA,CAAWN,CAAAA,CAAwBC,CAAAA,CAAM9B,CAAO,CAAA,CACtD,OAAImC,CAAAA,CACK,CACL,KAAA,CAAOA,CAAAA,CAAS,SAAA,CAAU,KAAA,CAC1B,YAAA,CAAcA,CAAAA,CAAS,YAAA,CACvB,MAAA,CAAQL,CAAAA,CAAK,cAAA,CAAiB,iBAAA,CAAoB,mBACpD,CAAA,CAGK,CACL,KAAA,CAAO,MAAA,CACP,YAAA,CAAc,MAAA,CACd,MAAA,CAAQ,mBACV,CACF,CCxTO,IAAMM,CAAAA,CAAc,OAAA,CAerBC,CAAAA,CAAI,UAAA,CACJC,CAAAA,CAAMD,CAAAA,CAAE,QAAA,CAODE,CAAAA,CAAN,KAAkB,CACN,MAAA,CAA4B,EAAC,CACtC,KAAA,CAA+C,IAAA,CACtC,OAAA,CACA,kBAAA,CAA0C,IAAA,CAE3D,WAAA,CAAYC,CAAAA,CAA6B,CACvC,KAAK,OAAA,CAAUA,CAAAA,CACf,IAAA,CAAK,KAAA,CAAQ,WAAA,CAAY,IAAM,IAAA,CAAK,KAAA,EAAM,CAAG,IAAA,CAAK,OAAA,CAAQ,eAAe,CAAA,CAErEF,CAAAA,EAAK,gBAAA,GACP,IAAA,CAAK,kBAAA,CAAqB,IAAM,CAC1BA,CAAAA,CAAI,eAAA,GAAoB,QAAA,EAC1B,IAAA,CAAK,WAAA,GAET,CAAA,CACAA,CAAAA,CAAI,gBAAA,CAAiB,kBAAA,CAAoB,IAAA,CAAK,kBAAkB,CAAA,EAEpE,CAEA,IAAA,CAAKG,CAAAA,CAA8B,CACjC,IAAA,CAAK,MAAA,CAAO,IAAA,CAAKA,CAAK,CAAA,CAClB,IAAA,CAAK,MAAA,CAAO,MAAA,EAAU,IAAA,CAAK,OAAA,CAAQ,YAAA,EACrC,IAAA,CAAK,KAAA,GAET,CAEQ,YAAA,CAAaC,CAAAA,CAAkD,CACrE,OAAO,CACL,IAAA,CAAM,CACJ,GAAG,IAAA,CAAK,OAAA,CAAQ,KAChB,UAAA,CAAYN,CACd,CAAA,CACA,MAAA,CAAQM,CACV,CACF,CAEA,KAAA,EAAc,CACZ,GAAI,IAAA,CAAK,MAAA,CAAO,MAAA,GAAW,CAAA,CACzB,OAEF,IAAMA,CAAAA,CAAQ,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,CAAA,CAAG,IAAA,CAAK,OAAA,CAAQ,YAAY,CAAA,CACvDC,CAAAA,CAAU,IAAA,CAAK,YAAA,CAAaD,CAAK,CAAA,CAEvC,MAAM,CAAA,EAAG,IAAA,CAAK,OAAA,CAAQ,OAAO,CAAA,gBAAA,CAAA,CAAoB,CAC/C,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CACP,cAAA,CAAgB,kBAAA,CAChB,aAAA,CAAe,CAAA,OAAA,EAAU,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAA,CAC9C,CAAA,CACA,IAAA,CAAM,IAAA,CAAK,SAAA,CAAUC,CAAO,CAC9B,CAAC,CAAA,CAAE,KAAA,CAAM,IAAM,CAEf,CAAC,EACH,CAMQ,WAAA,EAAoB,CAC1B,GAAI,IAAA,CAAK,MAAA,CAAO,MAAA,GAAW,CAAA,CACzB,OAGF,IAAMD,CAAAA,CAAQ,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,CAAA,CAAG,IAAA,CAAK,OAAA,CAAQ,YAAY,CAAA,CACvDC,CAAAA,CAAU,IAAA,CAAK,YAAA,CAAaD,CAAK,CAAA,CAEvC,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,OAAA,CAAQ,OAAO,CAAA,gBAAA,CAAA,CAAoB,CAC/C,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CACP,cAAA,CAAgB,kBAAA,CAChB,aAAA,CAAe,CAAA,OAAA,EAAU,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAA,CAC9C,CAAA,CACA,IAAA,CAAM,IAAA,CAAK,SAAA,CAAUC,CAAO,CAAA,CAC5B,SAAA,CAAW,IACb,CAAC,CAAA,CAAE,KAAA,CAAM,IAAM,CAEf,CAAC,EACH,CAEA,OAAA,EAAgB,CACV,KAAK,KAAA,GACP,aAAA,CAAc,IAAA,CAAK,KAAK,CAAA,CACxB,IAAA,CAAK,KAAA,CAAQ,IAAA,CAAA,CAEX,IAAA,CAAK,kBAAA,EAAsBL,CAAAA,EAAK,mBAAA,EAClCA,CAAAA,CAAI,mBAAA,CAAoB,kBAAA,CAAoB,IAAA,CAAK,kBAAkB,CAAA,CAErE,IAAA,CAAK,KAAA,GACP,CACF,CAAA,CC1GA,IAAMM,CAAAA,CAAmB,kCAAA,CAIzB,SAASC,CAAAA,EAA8B,CACrC,GAAI,CACF,IAAMR,CAAAA,CAAI,UAAA,CACJS,CAAAA,CAAMT,CAAAA,CAAE,SAAA,CAGd,GAAIS,CAAAA,EAAOA,CAAAA,CAAI,OAAA,GAAY,aAAA,CACzB,OAAO,cAAA,CAET,IAAMC,CAAAA,CAAMV,CAAAA,CAAE,MAAA,CACd,GAAIU,CAAAA,EAAO,OAAOA,CAAAA,CAAI,QAAA,CAAa,GAAA,CACjC,OAAO,SAAA,CAGT,GADaV,CAAAA,CAAE,OAAA,EACL,QAAA,EAAU,IAAA,CAClB,OAAO,MAAA,CAET,GAAI,OAAO,UAAA,CAAe,GAAA,CACxB,OAAO,MAEX,CAAA,KAAQ,CAER,CACA,OAAO,SACT,CAEA,IAAMW,CAAAA,CAAeH,CAAAA,EAAe,CAE9BI,CAAAA,CAAQ,UAAA,CAAuC,OAAA,CAG/CC,CAAAA,CAAY,OAAOD,CAAAA,EAAM,MAAA,EAAQ,MAAA,EAAW,UAAA,CAElD,SAASE,CAAAA,EAAyB,CAChC,OAAID,CAAAA,CAEKD,CAAAA,CAAM,MAAA,CAAQ,MAAA,EAAQ,CAE3B,OAAO,WAAA,CAAgB,GAAA,CAClB,WAAA,CAAY,GAAA,EAAI,CAElB,IAAA,CAAK,GAAA,EACd,CAEA,SAASG,CAAAA,CAAUC,CAAAA,CAAgC,CACjD,IAAMC,CAAAA,CAAMH,CAAAA,EAAM,CAClB,OAAI,OAAOE,CAAAA,EAAU,QAAA,EAAY,OAAOC,CAAAA,EAAQ,QAAA,CAEvC,MAAA,CAAA,CAAQA,CAAAA,CAAMD,GAAS,KAAK,CAAA,CAG9B,IAAA,CAAK,KAAA,CAAA,CAAQC,CAAAA,CAAkBD,CAAAA,EAAoB,GAAI,CAChE,CA6DA,IAAME,CAAAA,CAAN,KAAuC,CACpB,MAAA,CACA,WAAA,CACA,OAAA,CACA,WAAA,CACT,QAAA,CAAuC,IAAA,CACvC,iBAAA,CAAuC,EAAC,CAC/B,eAAA,CAAmC,IAAI,GAAA,CAChD,WAAA,CAAkC,IAAA,CACzB,aAAA,CACA,qBAAA,CACA,kBAAA,CAER,KAET,WAAA,CAAYf,CAAAA,CAAyB,CACnC,IAAA,CAAK,MAAA,CAASA,CAAAA,CAAQ,MAAA,CACtB,IAAA,CAAK,WAAA,CAAcA,CAAAA,CAAQ,WAAA,CAC3B,IAAA,CAAK,OAAA,CAAUA,CAAAA,CAAQ,OAAA,EAAWI,CAAAA,CAClC,IAAA,CAAK,aAAA,CAAgBJ,CAAAA,CAAQ,MAAA,EAAQ,OAAA,EAAW,IAAA,CAChD,IAAA,CAAK,qBAAA,CAAwBA,CAAAA,CAAQ,MAAA,EAAQ,eAAA,EAAmB,GAAA,CAChE,IAAA,CAAK,kBAAA,CAAqBA,EAAQ,MAAA,EAAQ,YAAA,EAAgB,GAAA,CAC1D,IAAA,CAAK,WAAA,CAAc,IAAA,CAAK,IAAA,EAAK,CAE7B,IAAA,CAAK,IAAA,CAAO,CACV,SAAA,CAAW,IAAA,CAAK,aAAA,CAAc,IAAA,CAAK,IAAI,CAAA,CACvC,GAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA,CAC3B,QAAA,CAAU,IAAA,CAAK,YAAA,CAAa,IAAA,CAAK,IAAI,CAAA,CACrC,KAAA,CAAO,KAAK,SAAA,CAAU,IAAA,CAAK,IAAI,CACjC,CAAA,CAEA,IAAMgB,CAAAA,CAAiBhB,CAAAA,CAAQ,OAAA,EAAS,OAAA,EAAW,IAAA,CAC7CiB,CAAAA,CAAoBjB,CAAAA,CAAQ,OAAA,EAAS,UAAA,EAAc,GAAA,CAErDgB,CAAAA,EACF,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,IAAM,CAC1B,WAAA,CAAY,SAAY,CACtB,GAAI,CACF,IAAME,CAAAA,CAAkB,IAAA,CAAK,UAAU,OAAA,CAEvC,GADA,MAAM,IAAA,CAAK,OAAA,EAAQ,CACf,IAAA,CAAK,QAAA,EAAY,IAAA,CAAK,QAAA,CAAS,OAAA,GAAYA,CAAAA,CAC7C,IAAA,IAAWC,CAAAA,IAAM,IAAA,CAAK,eAAA,CACpBA,CAAAA,GAGN,CAAA,MAASC,CAAAA,CAAO,CACd,OAAA,CAAQ,IAAA,CAAK,iCAAA,CAAmCA,CAAK,EACvD,CACF,CAAA,CAAGH,CAAiB,EACtB,CAAC,EAEL,CAEA,MAAc,IAAA,EAAsB,CAClC,IAAMI,CAAAA,CAAe,MAAM,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,SAAA,CAAA,CAAa,CAC3D,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CAAE,cAAA,CAAgB,kBAAmB,CAAA,CAC9C,IAAA,CAAM,IAAA,CAAK,SAAA,CAAU,CAAE,MAAA,CAAQ,IAAA,CAAK,MAAO,CAAC,CAC9C,CAAC,CAAA,CAED,GAAI,CAACA,CAAAA,CAAa,EAAA,CAAI,CACpB,IAAMD,CAAAA,CAAQ,MAAMC,CAAAA,CAAa,IAAA,EAAK,CAAE,KAAA,CAAM,KAAO,EAAC,CAAE,CAAA,CACxD,MAAM,IAAI,KAAA,CACR,CAAA,gCAAA,EAAoCD,CAAAA,CAA6B,KAAA,EAASC,CAAAA,CAAa,UAAU,CAAA,CACnG,CACF,CAEA,IAAMC,CAAAA,CAAY,MAAMD,CAAAA,CAAa,IAAA,EAAK,CAK1C,GAAI,CAACC,CAAAA,CAAS,KAAA,CACZ,MAAM,IAAI,KAAA,CACR,CAAA,2BAAA,EAA8BA,CAAAA,CAAS,KAAA,EAAS,eAAe,CAAA,CACjE,CAAA,CAGF,IAAMC,CAAAA,CAAmB,MAAM,KAAA,CAC7B,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,0BAAA,EAA6B,kBAAA,CAAmB,IAAA,CAAK,WAAW,CAAC,CAAA,CAAA,CAChF,CAAE,QAAS,CAAE,aAAA,CAAe,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAG,CAAE,CACxD,CAAA,CAEA,GAAI,CAACA,CAAAA,CAAiB,EAAA,CAAI,CACxB,IAAMH,CAAAA,CAAQ,MAAMG,CAAAA,CAAiB,IAAA,EAAK,CAAE,KAAA,CAAM,KAAO,EAAC,CAAE,CAAA,CAC5D,MAAM,IAAI,KAAA,CACR,CAAA,oCAAA,EAAwCH,CAAAA,CAA6B,OAASG,CAAAA,CAAiB,UAAU,CAAA,CAC3G,CACF,CAEA,IAAA,CAAK,QAAA,CAAY,MAAMA,CAAAA,CAAiB,IAAA,EAAK,CAEzC,IAAA,CAAK,aAAA,EAAiB,IAAA,CAAK,QAAA,CAAS,IAAA,GACtC,IAAA,CAAK,WAAA,CAAc,IAAIxB,CAAAA,CAAY,CACjC,OAAA,CAAS,IAAA,CAAK,OAAA,CACd,MAAA,CAAQ,IAAA,CAAK,MAAA,CACb,IAAA,CAAM,CACJ,SAAA,CAAW,KAAK,QAAA,CAAS,IAAA,CAAK,SAAA,CAC9B,cAAA,CAAgB,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,cAAA,CACnC,aAAA,CAAe,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,aAAA,CAClC,WAAA,CAAaS,CACf,CAAA,CACA,eAAA,CAAiB,IAAA,CAAK,qBAAA,CACtB,YAAA,CAAc,IAAA,CAAK,kBACrB,CAAC,CAAA,EAEL,CAEQ,WAAA,EAAmC,CACzC,GAAI,CAAC,IAAA,CAAK,SACR,MAAM,IAAI,KAAA,CACR,6DACF,CAAA,CAEF,OAAO,IAAA,CAAK,QACd,CAEQ,YAAA,CAAaR,CAAAA,CAEC,CACpB,IAAMwB,CAAAA,CAA4B,EAAC,CAC7BC,CAAAA,CAAW,IAAI,GAAA,CAAI,CACvB,GAAG,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,iBAAiB,CAAA,CACrC,GAAG,MAAA,CAAO,IAAA,CAAKzB,CAAAA,EAAS,SAAW,EAAE,CACvC,CAAC,CAAA,CACD,IAAA,IAAW0B,CAAAA,IAAQD,CAAAA,CACjBD,CAAAA,CAAOE,CAAI,CAAA,CAAI,CACb,GAAG,IAAA,CAAK,iBAAA,CAAkBA,CAAI,CAAA,CAC9B,GAAG1B,CAAAA,EAAS,OAAA,GAAU0B,CAAI,CAC5B,CAAA,CAEF,OAAOF,CACT,CAEQ,QAAA,CAASrC,CAAAA,CAAa3B,CAAAA,CAAqC,CACjE,IAAMmE,CAAAA,CAAW,IAAA,CAAK,WAAA,EAAY,CAClC,GAAI,CAACA,CAAAA,CAAS,KAAA,CACZ,OAEF,IAAMrC,CAAAA,CAAOqC,CAAAA,CAAS,KAAA,CAAMxC,CAAG,CAAA,CAC/B,GAAI,CAACG,CAAAA,CAAM,CACT,IAAA,CAAK,UAAA,CAAW,CACd,OAAA,CAASH,CAAAA,CACT,YAAA,CAAc,MAAA,CACd,KAAA,CAAO,MAAA,CACP,MAAA,CAAQ,gBAAA,CACR,QAAA3B,CAAAA,CACA,iBAAA,CAAmBmE,CAAAA,CAAS,OAC9B,CAAC,CAAA,CACD,MACF,CAEA,IAAMC,CAAAA,CAAYjB,CAAAA,EAAM,CAEpBkB,CAAAA,CACJ,GAAI,CACFA,CAAAA,CAAStC,CAAAA,CAAaD,CAAAA,CAAM9B,CAAAA,CAASmE,CAAAA,CAAS,QAAA,EAAY,EAAE,EAC9D,CAAA,MAASG,CAAAA,CAAK,CAEZD,CAAAA,CAAS,CACP,KAAA,CAAO,OACP,YAAA,CAAc,MAAA,CACd,MAAA,CAAQ,OAAA,CACR,WAAA,CALkBC,CAAAA,YAAe,KAAA,CAAQA,CAAAA,CAAI,OAAA,CAAU,MAAA,CAAOA,CAAG,CAMnE,EACF,CAEA,IAAMC,CAAAA,CAAuBnB,CAAAA,CAAUgB,CAAS,CAAA,CAEhD,OAAA,IAAA,CAAK,UAAA,CAAW,CACd,OAAA,CAASzC,CAAAA,CACT,YAAA,CAAc0C,CAAAA,CAAO,YAAA,CACrB,KAAA,CAAOA,CAAAA,CAAO,KAAA,CACd,OAAQA,CAAAA,CAAO,MAAA,CACf,OAAA,CAAArE,CAAAA,CACA,iBAAA,CAAmBqE,CAAAA,CAAO,iBAAA,CAC1B,iBAAA,CAAmBF,CAAAA,CAAS,OAAA,CAC5B,WAAA,CAAaE,CAAAA,CAAO,WAAA,CACpB,oBAAA,CAAAE,CACF,CAAC,CAAA,CAEMF,CAAAA,CAAO,KAChB,CAEQ,UAAA,CAAWG,CAAAA,CAUV,CACP,GAAI,CAAC,IAAA,CAAK,WAAA,CACR,OAEF,GAAM,CAAE,QAAAxE,CAAQ,CAAA,CAAIwE,CAAAA,CACdC,CAAAA,CAAe,MAAA,CAAO,IAAA,CAAKzE,CAAO,CAAA,CAClC0E,CAAAA,CAAwC,EAAC,CAC/C,IAAA,IAAWR,CAAAA,IAAQO,CAAAA,CACjBC,CAAAA,CAAYR,CAAI,CAAA,CAAI,MAAA,CAAO,IAAA,CAAKlE,CAAAA,CAAQkE,CAAI,CAAA,EAAK,EAAE,CAAA,CAGrD,IAAMS,CAAAA,CACJF,CAAAA,CAAa,MAAA,GAAW,CAAA,EACxBA,EAAa,KAAA,CACVP,CAAAA,EAAS,MAAA,CAAO,IAAA,CAAKlE,CAAAA,CAAQkE,CAAI,CAAA,EAAK,EAAE,CAAA,CAAE,MAAA,GAAW,CACxD,CAAA,CAEF,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,CACpB,OAAA,CAASM,CAAAA,CAAO,OAAA,CAChB,YAAA,CAAcA,CAAAA,CAAO,YAAA,CACrB,KAAA,CAAOA,CAAAA,CAAO,KAAA,CACd,MAAA,CAAQA,CAAAA,CAAO,MAAA,CACf,YAAA,CAAAC,EACA,WAAA,CAAAC,CAAAA,CACA,SAAA,CAAW,IAAA,CAAK,GAAA,EAAI,CACpB,iBAAA,CAAmBF,CAAAA,CAAO,iBAAA,CAC1B,iBAAA,CAAmBA,CAAAA,CAAO,iBAAA,CAC1B,WAAA,CAAaA,CAAAA,CAAO,WAAA,CACpB,oBAAA,CAAsBA,CAAAA,CAAO,oBAAA,CAC7B,WAAA,CAAAG,CACF,CAAC,EACH,CAEA,MAAM,KAAA,EAAuB,CAC3B,MAAM,IAAA,CAAK,YACb,CAEA,SAAmB,CACjB,OAAO,IAAA,CAAK,QAAA,GAAa,IAC3B,CAEA,MAAM,SAAA,CAAUhD,CAAAA,CAAaa,CAAAA,CAA8C,CACzE,MAAM,IAAA,CAAK,WAAA,CACX,IAAMxB,CAAAA,CAAQ,IAAA,CAAK,QAAA,CAASW,CAAAA,CAAK,IAAA,CAAK,YAAA,CAAaa,CAAO,CAAC,CAAA,CAC3D,OAAO,OAAOxB,CAAAA,EAAU,SAAA,CAAYA,CAAAA,CAAQ,KAC9C,CAEA,MAAM,GAAA,CAAOW,CAAAA,CAAaa,CAAAA,CAAqC,CAC7D,MAAM,IAAA,CAAK,WAAA,CACX,IAAMxB,CAAAA,CAAQ,IAAA,CAAK,QAAA,CAASW,CAAAA,CAAK,IAAA,CAAK,YAAA,CAAaa,CAAO,CAAC,CAAA,CAC3D,OAA8BxB,CAAAA,EAE1BwB,CAAAA,CAAQ,QACd,CAEQ,aAAA,CAAcb,CAAAA,CAAaa,CAAAA,CAAqC,CACtE,IAAMxB,CAAAA,CAAQ,IAAA,CAAK,SAASW,CAAAA,CAAK,IAAA,CAAK,YAAA,CAAaa,CAAO,CAAC,CAAA,CAC3D,OAAO,OAAOxB,CAAAA,EAAU,SAAA,CAAYA,CAAAA,CAAQ,KAC9C,CAEQ,OAAA,CAAWW,CAAAA,CAAaa,CAAAA,CAA4B,CAC1D,IAAMxB,CAAAA,CAAQ,IAAA,CAAK,QAAA,CAASW,CAAAA,CAAK,IAAA,CAAK,YAAA,CAAaa,CAAO,CAAC,CAAA,CAC3D,OAA8BxB,CAAAA,EAE1BwB,CAAAA,CAAQ,QACd,CAEQ,YAAA,CACNb,CAAAA,CACAa,CAAAA,CACY,CACZ,IAAM2B,CAAAA,CAAW,IAAA,CAAK,WAAA,EAAY,CAC5BnE,CAAAA,CAAU,IAAA,CAAK,YAAA,CAAawC,CAAO,CAAA,CAEzC,GAAI,CAAC2B,CAAAA,CAAS,KAAA,CACZ,OAAO,CACL,KAAA,CAAO,MAAA,CACP,YAAA,CAAc,MAAA,CACd,MAAA,CAAQ,gBAAA,CACR,iBAAA,CAAmBA,CAAAA,CAAS,OAC9B,EAGF,IAAMrC,CAAAA,CAAOqC,CAAAA,CAAS,KAAA,CAAMxC,CAAG,CAAA,CAC/B,GAAI,CAACG,CAAAA,CACH,OAAO,CACL,KAAA,CAAO,MAAA,CACP,YAAA,CAAc,MAAA,CACd,MAAA,CAAQ,gBAAA,CACR,iBAAA,CAAmBqC,CAAAA,CAAS,OAC9B,CAAA,CAGF,IAAMC,CAAAA,CAAYjB,CAAAA,EAAM,CAEpBkB,CAAAA,CACJ,GAAI,CACFA,CAAAA,CAAStC,CAAAA,CAAaD,EAAM9B,CAAAA,CAASmE,CAAAA,CAAS,QAAA,EAAY,EAAE,EAC9D,CAAA,MAASG,CAAAA,CAAK,CAEZD,CAAAA,CAAS,CACP,KAAA,CAAO,MAAA,CACP,YAAA,CAAc,MAAA,CACd,MAAA,CAAQ,OAAA,CACR,WAAA,CALkBC,CAAAA,YAAe,KAAA,CAAQA,CAAAA,CAAI,OAAA,CAAU,MAAA,CAAOA,CAAG,CAMnE,EACF,CAEA,OAAO,CACL,KAAA,CAAOD,EAAO,KAAA,CACd,YAAA,CAAcA,CAAAA,CAAO,YAAA,CACrB,MAAA,CAAQA,CAAAA,CAAO,MAAA,CACf,iBAAA,CAAmBA,CAAAA,CAAO,iBAAA,CAC1B,WAAA,CAAaA,CAAAA,CAAO,WAAA,CACpB,oBAAA,CAAsBjB,CAAAA,CAAUgB,CAAS,CAAA,CACzC,iBAAA,CAAmBD,CAAAA,CAAS,OAC9B,CACF,CAEQ,SAAA,CACNxC,CAAAA,CACAiD,CAAAA,CACA5E,CAAAA,CACM,CACN,IAAA,CAAK,UAAA,CAAW,CACd,QAAS2B,CAAAA,CACT,YAAA,CAAciD,CAAAA,CAAO,YAAA,CACrB,KAAA,CAAOA,CAAAA,CAAO,KAAA,CACd,MAAA,CAAQA,CAAAA,CAAO,MAAA,CACf,OAAA,CAAS,IAAA,CAAK,YAAA,CAAa,CAAE,OAAA,CAAA5E,CAAQ,CAAC,CAAA,CACtC,iBAAA,CAAmB4E,CAAAA,CAAO,iBAAA,CAC1B,iBAAA,CAAmBA,CAAAA,CAAO,iBAAA,CAC1B,WAAA,CAAaA,CAAAA,CAAO,WAAA,CACpB,oBAAA,CAAsBA,CAAAA,CAAO,oBAC/B,CAAC,EACH,CAEA,QAAA,CAAS5E,CAAAA,CAAkC,CACzC,IAAA,CAAK,iBAAA,CAAoB,CAAE,GAAGA,CAAQ,EACxC,CAEA,KAAA,EAAc,CACZ,IAAA,CAAK,iBAAA,CAAoB,GAC3B,CAEA,MAAM,OAAA,EAAyB,CAC7B,IAAM6E,CAAAA,CAAW,MAAM,KAAA,CACrB,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,0BAAA,EAA6B,mBAAmB,IAAA,CAAK,WAAW,CAAC,CAAA,CAAA,CAChF,CAAE,OAAA,CAAS,CAAE,aAAA,CAAe,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAG,CAAE,CACxD,CAAA,CAEA,GAAI,CAACA,CAAAA,CAAS,EAAA,CAAI,CAChB,IAAMjB,CAAAA,CAAQ,MAAMiB,CAAAA,CAAS,IAAA,EAAK,CAAE,KAAA,CAAM,KAAO,EAAC,CAAE,EACpD,MAAM,IAAI,KAAA,CACR,CAAA,6BAAA,EAAiCjB,CAAAA,CAA6B,KAAA,EAASiB,CAAAA,CAAS,UAAU,CAAA,CAC5F,CACF,CAEA,IAAA,CAAK,QAAA,CAAY,MAAMA,CAAAA,CAAS,IAAA,GAClC,CAEA,WAAA,EAA0C,CACxC,OAAO,IAAA,CAAK,QACd,CAEA,QAAA,CAASC,CAAAA,CAAkC,CACzC,OAAA,IAAA,CAAK,eAAA,CAAgB,GAAA,CAAIA,CAAQ,CAAA,CAC1B,IAAM,IAAA,CAAK,eAAA,CAAgB,MAAA,CAAOA,CAAQ,CACnD,CAEA,KAAA,EAAc,CACR,IAAA,CAAK,WAAA,GACP,IAAA,CAAK,WAAA,CAAY,OAAA,EAAQ,CACzB,IAAA,CAAK,WAAA,CAAc,IAAA,EAEvB,CACF,CAAA,CAuBO,SAASC,CAAAA,CAAcvC,CAAAA,CAAkC,CAC9D,OAAO,IAAIe,CAAAA,CAAcf,CAAO,CAClC","file":"index.js","sourcesContent":["import type {\n EvaluationContext,\n EvaluationResult,\n SnapshotFlag,\n SnapshotRollout,\n SnapshotRuleCondition,\n SnapshotSegment,\n SnapshotTarget,\n SnapshotVariation,\n} from \"./types\";\n\nfunction hashString(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n // biome-ignore lint/suspicious/noBitwiseOperators: intentional hash algorithm using bitwise shift\n hash = (hash << 5) - hash + char;\n // biome-ignore lint/suspicious/noBitwiseOperators: converting to 32-bit integer\n hash |= 0;\n }\n return Math.abs(hash);\n}\n\nfunction getBucketValue(\n flagKey: string,\n context: EvaluationContext,\n rollout: SnapshotRollout\n): number {\n const bucketKey =\n context[rollout.bucketContextKind]?.[rollout.bucketAttributeKey];\n const seed = rollout.seed ?? \"\";\n const hashInput = `${flagKey}:${seed}:${String(bucketKey ?? \"anonymous\")}`;\n return hashString(hashInput) % 100_000;\n}\n\nfunction selectVariationFromRollout(\n rollout: SnapshotRollout,\n bucketValue: number,\n variations: Record<string, SnapshotVariation>\n): SnapshotVariation | undefined {\n let cumulative = 0;\n\n for (const rv of rollout.variations) {\n cumulative += rv.weight;\n if (bucketValue < cumulative) {\n return variations[rv.variationKey];\n }\n }\n\n const lastVariation = rollout.variations.at(-1);\n return lastVariation ? variations[lastVariation.variationKey] : undefined;\n}\n\nfunction evaluateCondition(\n condition: SnapshotRuleCondition,\n context: EvaluationContext\n): boolean {\n const { contextKind, attributeKey, operator, value } = condition;\n const contextValue = context[contextKind]?.[attributeKey];\n\n switch (operator) {\n case \"equals\":\n return contextValue === value;\n\n case \"not_equals\":\n return contextValue !== value;\n\n case \"contains\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.includes(value);\n }\n if (Array.isArray(contextValue)) {\n return contextValue.includes(value);\n }\n return false;\n\n case \"not_contains\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return !contextValue.includes(value);\n }\n if (Array.isArray(contextValue)) {\n return !contextValue.includes(value);\n }\n return true;\n\n case \"starts_with\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.startsWith(value);\n }\n return false;\n\n case \"ends_with\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.endsWith(value);\n }\n return false;\n\n case \"greater_than\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue > value;\n }\n return false;\n\n case \"less_than\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue < value;\n }\n return false;\n\n case \"greater_than_or_equal\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue >= value;\n }\n return false;\n\n case \"less_than_or_equal\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue <= value;\n }\n return false;\n\n case \"in\":\n if (Array.isArray(value)) {\n return value.includes(contextValue);\n }\n return false;\n\n case \"not_in\":\n if (Array.isArray(value)) {\n return !value.includes(contextValue);\n }\n return true;\n\n case \"exists\":\n return contextValue !== undefined && contextValue !== null;\n\n case \"not_exists\":\n return contextValue === undefined || contextValue === null;\n\n default:\n return false;\n }\n}\n\nfunction evaluateConditions(\n conditions: SnapshotRuleCondition[],\n context: EvaluationContext\n): boolean {\n return conditions.every((condition) => evaluateCondition(condition, context));\n}\n\nfunction evaluateSegment(\n segment: SnapshotSegment,\n context: EvaluationContext\n): boolean {\n return evaluateConditions(segment.conditions, context);\n}\n\nfunction evaluateTarget(\n target: SnapshotTarget,\n context: EvaluationContext,\n segments: Record<string, SnapshotSegment>\n): boolean {\n switch (target.type) {\n case \"individual\":\n if (\n target.contextKind &&\n target.attributeKey &&\n target.attributeValue !== undefined\n ) {\n return (\n context[target.contextKind]?.[target.attributeKey] ===\n target.attributeValue\n );\n }\n return false;\n\n case \"rule\":\n if (target.conditions) {\n return evaluateConditions(target.conditions, context);\n }\n return false;\n\n case \"segment\":\n if (target.segmentKey) {\n const segment = segments[target.segmentKey];\n if (segment) {\n return evaluateSegment(segment, context);\n }\n }\n return false;\n\n default:\n return false;\n }\n}\n\ninterface ResolvedVariation {\n variation: SnapshotVariation;\n variationKey: string;\n}\n\nfunction resolveTargetVariation(\n target: SnapshotTarget,\n flagKey: string,\n context: EvaluationContext,\n variations: Record<string, SnapshotVariation>\n): ResolvedVariation | undefined {\n if (target.rollout) {\n const bucketValue = getBucketValue(flagKey, context, target.rollout);\n const variation = selectVariationFromRollout(\n target.rollout,\n bucketValue,\n variations\n );\n if (variation) {\n const key = Object.keys(variations).find(\n (k) => variations[k] === variation\n );\n return key ? { variation, variationKey: key } : undefined;\n }\n return undefined;\n }\n\n if (target.variationKey) {\n const variation = variations[target.variationKey];\n return variation\n ? { variation, variationKey: target.variationKey }\n : undefined;\n }\n\n return undefined;\n}\n\nfunction resolveDefaultVariation(\n flag: SnapshotFlag,\n context: EvaluationContext\n): ResolvedVariation | undefined {\n if (flag.defaultRollout) {\n const bucketValue = getBucketValue(flag.key, context, flag.defaultRollout);\n const variation = selectVariationFromRollout(\n flag.defaultRollout,\n bucketValue,\n flag.variations\n );\n if (variation) {\n const key = Object.keys(flag.variations).find(\n (k) => flag.variations[k] === variation\n );\n return key ? { variation, variationKey: key } : undefined;\n }\n return undefined;\n }\n\n if (flag.defaultVariationKey) {\n const variation = flag.variations[flag.defaultVariationKey];\n return variation\n ? { variation, variationKey: flag.defaultVariationKey }\n : undefined;\n }\n\n return undefined;\n}\n\nexport function evaluateFlag(\n flag: SnapshotFlag,\n context: EvaluationContext,\n segments: Record<string, SnapshotSegment>\n): EvaluationResult {\n if (!flag.enabled) {\n const offVariation = flag.variations[flag.offVariationKey];\n return {\n value: offVariation?.value,\n variationKey: flag.offVariationKey,\n reason: \"FLAG_DISABLED\",\n };\n }\n\n const sortedTargets = [...flag.targets].sort(\n (a, b) => a.sortOrder - b.sortOrder\n );\n\n for (const target of sortedTargets) {\n if (evaluateTarget(target, context, segments)) {\n const resolved = resolveTargetVariation(\n target,\n flag.key,\n context,\n flag.variations\n );\n if (resolved) {\n return {\n value: resolved.variation.value,\n variationKey: resolved.variationKey,\n reason: \"TARGET_MATCH\",\n matchedTargetName: target.name,\n };\n }\n }\n }\n\n const resolved = resolveDefaultVariation(flag, context);\n if (resolved) {\n return {\n value: resolved.variation.value,\n variationKey: resolved.variationKey,\n reason: flag.defaultRollout ? \"DEFAULT_ROLLOUT\" : \"DEFAULT_VARIATION\",\n };\n }\n\n return {\n value: undefined,\n variationKey: undefined,\n reason: \"DEFAULT_VARIATION\",\n };\n}\n","import type { EvaluationBatchPayload, EvaluationEvent } from \"./types\";\n\ndeclare const __SDK_VERSION__: string;\nexport const SDK_VERSION = __SDK_VERSION__;\n\ninterface EventBufferOptions {\n baseUrl: string;\n apiKey: string;\n meta: {\n projectId: string;\n organizationId: string;\n environmentId: string;\n sdkPlatform?: string;\n };\n flushIntervalMs: number;\n maxBatchSize: number;\n}\n\nconst g = globalThis as Record<string, unknown>;\nconst doc = g.document as\n | {\n visibilityState?: string;\n addEventListener?: (event: string, handler: () => void) => void;\n removeEventListener?: (event: string, handler: () => void) => void;\n }\n | undefined;\nexport class EventBuffer {\n private readonly events: EvaluationEvent[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private readonly options: EventBufferOptions;\n private readonly onVisibilityChange: (() => void) | null = null;\n\n constructor(options: EventBufferOptions) {\n this.options = options;\n this.timer = setInterval(() => this.flush(), this.options.flushIntervalMs);\n\n if (doc?.addEventListener) {\n this.onVisibilityChange = () => {\n if (doc.visibilityState === \"hidden\") {\n this.flushBeacon();\n }\n };\n doc.addEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n }\n\n push(event: EvaluationEvent): void {\n this.events.push(event);\n if (this.events.length >= this.options.maxBatchSize) {\n this.flush();\n }\n }\n\n private buildPayload(batch: EvaluationEvent[]): EvaluationBatchPayload {\n return {\n meta: {\n ...this.options.meta,\n sdkVersion: SDK_VERSION,\n },\n events: batch,\n };\n }\n\n flush(): void {\n if (this.events.length === 0) {\n return;\n }\n const batch = this.events.splice(0, this.options.maxBatchSize);\n const payload = this.buildPayload(batch);\n\n fetch(`${this.options.baseUrl}/sdk/evaluations`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.options.apiKey}`,\n },\n body: JSON.stringify(payload),\n }).catch(() => {\n // Fire-and-forget: silently drop failed events to prevent unbounded growth\n });\n }\n\n /**\n * Flush with keepalive flag for reliable delivery during page unload.\n * keepalive fetch survives page navigation like sendBeacon but supports headers.\n */\n private flushBeacon(): void {\n if (this.events.length === 0) {\n return;\n }\n\n const batch = this.events.splice(0, this.options.maxBatchSize);\n const payload = this.buildPayload(batch);\n\n fetch(`${this.options.baseUrl}/sdk/evaluations`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.options.apiKey}`,\n },\n body: JSON.stringify(payload),\n keepalive: true,\n }).catch(() => {\n // Fire-and-forget\n });\n }\n\n destroy(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.onVisibilityChange && doc?.removeEventListener) {\n doc.removeEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n this.flush();\n }\n}\n","import { evaluateFlag } from \"./evaluator\";\nimport { EventBuffer } from \"./event-buffer\";\nimport type {\n EnvironmentSnapshot,\n EvaluationContext,\n EvaluationResult,\n FlagOptions,\n GradualOptions,\n IsEnabledOptions,\n} from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://worker.gradual.so/api/v1\";\n\ntype SdkPlatform = \"browser\" | \"node\" | \"react-native\" | \"edge\" | \"unknown\";\n\nfunction detectPlatform(): SdkPlatform {\n try {\n const g = globalThis as Record<string, unknown>;\n const nav = g.navigator as\n | { product?: string; userAgent?: string }\n | undefined;\n if (nav && nav.product === \"ReactNative\") {\n return \"react-native\";\n }\n const win = g.window as { document?: unknown } | undefined;\n if (win && typeof win.document !== \"undefined\") {\n return \"browser\";\n }\n const proc = g.process as { versions?: { node?: string } } | undefined;\n if (proc?.versions?.node) {\n return \"node\";\n }\n if (typeof globalThis !== \"undefined\") {\n return \"edge\";\n }\n } catch {\n // Ignore detection errors\n }\n return \"unknown\";\n}\n\nconst SDK_PLATFORM = detectPlatform();\n\nconst proc = (globalThis as Record<string, unknown>).process as\n | { hrtime?: { bigint?: () => bigint } }\n | undefined;\nconst hasHrtime = typeof proc?.hrtime?.bigint === \"function\";\n\nfunction nowNs(): bigint | number {\n if (hasHrtime) {\n // biome-ignore lint/style/noNonNullAssertion: guarded by hasHrtime check\n return proc!.hrtime!.bigint!();\n }\n if (typeof performance !== \"undefined\") {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction elapsedUs(start: bigint | number): number {\n const end = nowNs();\n if (typeof start === \"bigint\" && typeof end === \"bigint\") {\n // hrtime bigint: nanoseconds → microseconds\n return Number((end - start) / 1000n);\n }\n // performance.now() ms or Date.now() ms → microseconds\n return Math.round(((end as number) - (start as number)) * 1000);\n}\n\nexport interface Gradual {\n /** Wait for the SDK to be ready (snapshot fetched) */\n ready(): Promise<void>;\n\n /** Check if the SDK is ready for sync access */\n isReady(): boolean;\n\n /** Check if a boolean flag is enabled */\n isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean>;\n\n /** Get a flag value with type inference from fallback */\n get<T>(key: string, options: FlagOptions<T>): Promise<T>;\n\n /** Set persistent user context for all evaluations */\n identify(context: EvaluationContext): void;\n\n /** Clear the identified user context */\n reset(): void;\n\n /** Refresh the snapshot from the server */\n refresh(): Promise<void>;\n\n /** Get the current snapshot (for debugging) */\n getSnapshot(): EnvironmentSnapshot | null;\n\n /** Subscribe to snapshot updates from polling (returns unsubscribe function) */\n onUpdate(callback: () => void): () => void;\n\n /** Flush pending evaluation events and stop the event buffer */\n close(): void;\n\n /** Sync methods (throw if not ready) */\n sync: GradualSync;\n}\n\nexport interface EvalDetail {\n value: unknown;\n variationKey: string | undefined;\n reason: EvaluationResult[\"reason\"];\n matchedTargetName?: string;\n errorDetail?: string;\n evaluationDurationUs?: number;\n flagConfigVersion?: number;\n}\n\nexport interface GradualSync {\n /** Sync version of isEnabled (throws if not ready) */\n isEnabled(key: string, options?: IsEnabledOptions): boolean;\n\n /** Sync version of get (throws if not ready) */\n get<T>(key: string, options: FlagOptions<T>): T;\n\n /** Evaluate a flag without tracking. Use with track() for React-safe evaluation. */\n evaluate(key: string, options?: { context?: EvaluationContext }): EvalDetail;\n\n /** Manually track an evaluation that was produced by evaluate(). */\n track(key: string, detail: EvalDetail, context?: EvaluationContext): void;\n}\n\nclass GradualClient implements Gradual {\n private readonly apiKey: string;\n private readonly environment: string;\n private readonly baseUrl: string;\n private readonly initPromise: Promise<void>;\n private snapshot: EnvironmentSnapshot | null = null;\n private identifiedContext: EvaluationContext = {};\n private readonly updateListeners: Set<() => void> = new Set();\n private eventBuffer: EventBuffer | null = null;\n private readonly eventsEnabled: boolean;\n private readonly eventsFlushIntervalMs: number;\n private readonly eventsMaxBatchSize: number;\n\n readonly sync: GradualSync;\n\n constructor(options: GradualOptions) {\n this.apiKey = options.apiKey;\n this.environment = options.environment;\n this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n this.eventsEnabled = options.events?.enabled ?? true;\n this.eventsFlushIntervalMs = options.events?.flushIntervalMs ?? 30_000;\n this.eventsMaxBatchSize = options.events?.maxBatchSize ?? 100;\n this.initPromise = this.init();\n\n this.sync = {\n isEnabled: this.isEnabledSync.bind(this),\n get: this.getSync.bind(this),\n evaluate: this.evaluateSync.bind(this),\n track: this.trackSync.bind(this),\n };\n\n const pollingEnabled = options.polling?.enabled ?? true;\n const pollingIntervalMs = options.polling?.intervalMs ?? 10_000;\n\n if (pollingEnabled) {\n this.initPromise.then(() => {\n setInterval(async () => {\n try {\n const previousVersion = this.snapshot?.version;\n await this.refresh();\n if (this.snapshot && this.snapshot.version !== previousVersion) {\n for (const cb of this.updateListeners) {\n cb();\n }\n }\n } catch (error) {\n console.warn(\"Gradual: Polling refresh failed\", error);\n }\n }, pollingIntervalMs);\n });\n }\n }\n\n private async init(): Promise<void> {\n const initResponse = await fetch(`${this.baseUrl}/sdk/init`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ apiKey: this.apiKey }),\n });\n\n if (!initResponse.ok) {\n const error = await initResponse.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to initialize - ${(error as { error?: string }).error ?? initResponse.statusText}`\n );\n }\n\n const initData = (await initResponse.json()) as {\n valid: boolean;\n error?: string;\n };\n\n if (!initData.valid) {\n throw new Error(\n `Gradual: Invalid API key - ${initData.error ?? \"Unknown error\"}`\n );\n }\n\n const snapshotResponse = await fetch(\n `${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,\n { headers: { Authorization: `Bearer ${this.apiKey}` } }\n );\n\n if (!snapshotResponse.ok) {\n const error = await snapshotResponse.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to fetch snapshot - ${(error as { error?: string }).error ?? snapshotResponse.statusText}`\n );\n }\n\n this.snapshot = (await snapshotResponse.json()) as EnvironmentSnapshot;\n\n if (this.eventsEnabled && this.snapshot.meta) {\n this.eventBuffer = new EventBuffer({\n baseUrl: this.baseUrl,\n apiKey: this.apiKey,\n meta: {\n projectId: this.snapshot.meta.projectId,\n organizationId: this.snapshot.meta.organizationId,\n environmentId: this.snapshot.meta.environmentId,\n sdkPlatform: SDK_PLATFORM,\n },\n flushIntervalMs: this.eventsFlushIntervalMs,\n maxBatchSize: this.eventsMaxBatchSize,\n });\n }\n }\n\n private ensureReady(): EnvironmentSnapshot {\n if (!this.snapshot) {\n throw new Error(\n \"Gradual: SDK not ready. Use await ready() or async methods.\"\n );\n }\n return this.snapshot;\n }\n\n private mergeContext(options?: {\n context?: EvaluationContext;\n }): EvaluationContext {\n const merged: EvaluationContext = {};\n const allKinds = new Set([\n ...Object.keys(this.identifiedContext),\n ...Object.keys(options?.context ?? {}),\n ]);\n for (const kind of allKinds) {\n merged[kind] = {\n ...this.identifiedContext[kind],\n ...options?.context?.[kind],\n };\n }\n return merged;\n }\n\n private evaluate(key: string, context: EvaluationContext): unknown {\n const snapshot = this.ensureReady();\n if (!snapshot.flags) {\n return undefined;\n }\n const flag = snapshot.flags[key];\n if (!flag) {\n this.trackEvent({\n flagKey: key,\n variationKey: undefined,\n value: undefined,\n reason: \"FLAG_NOT_FOUND\",\n context,\n flagConfigVersion: snapshot.version,\n });\n return undefined;\n }\n\n const startTime = nowNs();\n\n let result: EvaluationResult;\n try {\n result = evaluateFlag(flag, context, snapshot.segments ?? {});\n } catch (err) {\n const errorDetail = err instanceof Error ? err.message : String(err);\n result = {\n value: undefined,\n variationKey: undefined,\n reason: \"ERROR\",\n errorDetail,\n };\n }\n\n const evaluationDurationUs = elapsedUs(startTime);\n\n this.trackEvent({\n flagKey: key,\n variationKey: result.variationKey,\n value: result.value,\n reason: result.reason,\n context,\n matchedTargetName: result.matchedTargetName,\n flagConfigVersion: snapshot.version,\n errorDetail: result.errorDetail,\n evaluationDurationUs,\n });\n\n return result.value;\n }\n\n private trackEvent(params: {\n flagKey: string;\n variationKey: string | undefined;\n value: unknown;\n reason: EvaluationResult[\"reason\"];\n context: EvaluationContext;\n matchedTargetName?: string;\n flagConfigVersion?: number;\n errorDetail?: string;\n evaluationDurationUs?: number;\n }): void {\n if (!this.eventBuffer) {\n return;\n }\n const { context } = params;\n const contextKinds = Object.keys(context);\n const contextKeys: Record<string, string[]> = {};\n for (const kind of contextKinds) {\n contextKeys[kind] = Object.keys(context[kind] ?? {});\n }\n\n const isAnonymous =\n contextKinds.length === 0 ||\n contextKinds.every(\n (kind) => Object.keys(context[kind] ?? {}).length === 0\n );\n\n this.eventBuffer.push({\n flagKey: params.flagKey,\n variationKey: params.variationKey,\n value: params.value,\n reason: params.reason,\n contextKinds,\n contextKeys,\n timestamp: Date.now(),\n matchedTargetName: params.matchedTargetName,\n flagConfigVersion: params.flagConfigVersion,\n errorDetail: params.errorDetail,\n evaluationDurationUs: params.evaluationDurationUs,\n isAnonymous,\n });\n }\n\n async ready(): Promise<void> {\n await this.initPromise;\n }\n\n isReady(): boolean {\n return this.snapshot !== null;\n }\n\n async isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean> {\n await this.initPromise;\n const value = this.evaluate(key, this.mergeContext(options));\n return typeof value === \"boolean\" ? value : false;\n }\n\n async get<T>(key: string, options: FlagOptions<T>): Promise<T> {\n await this.initPromise;\n const value = this.evaluate(key, this.mergeContext(options));\n return value !== undefined && value !== null\n ? (value as T)\n : options.fallback;\n }\n\n private isEnabledSync(key: string, options?: IsEnabledOptions): boolean {\n const value = this.evaluate(key, this.mergeContext(options));\n return typeof value === \"boolean\" ? value : false;\n }\n\n private getSync<T>(key: string, options: FlagOptions<T>): T {\n const value = this.evaluate(key, this.mergeContext(options));\n return value !== undefined && value !== null\n ? (value as T)\n : options.fallback;\n }\n\n private evaluateSync(\n key: string,\n options?: { context?: EvaluationContext }\n ): EvalDetail {\n const snapshot = this.ensureReady();\n const context = this.mergeContext(options);\n\n if (!snapshot.flags) {\n return {\n value: undefined,\n variationKey: undefined,\n reason: \"FLAG_NOT_FOUND\",\n flagConfigVersion: snapshot.version,\n };\n }\n\n const flag = snapshot.flags[key];\n if (!flag) {\n return {\n value: undefined,\n variationKey: undefined,\n reason: \"FLAG_NOT_FOUND\",\n flagConfigVersion: snapshot.version,\n };\n }\n\n const startTime = nowNs();\n\n let result: EvaluationResult;\n try {\n result = evaluateFlag(flag, context, snapshot.segments ?? {});\n } catch (err) {\n const errorDetail = err instanceof Error ? err.message : String(err);\n result = {\n value: undefined,\n variationKey: undefined,\n reason: \"ERROR\",\n errorDetail,\n };\n }\n\n return {\n value: result.value,\n variationKey: result.variationKey,\n reason: result.reason,\n matchedTargetName: result.matchedTargetName,\n errorDetail: result.errorDetail,\n evaluationDurationUs: elapsedUs(startTime),\n flagConfigVersion: snapshot.version,\n };\n }\n\n private trackSync(\n key: string,\n detail: EvalDetail,\n context?: EvaluationContext\n ): void {\n this.trackEvent({\n flagKey: key,\n variationKey: detail.variationKey,\n value: detail.value,\n reason: detail.reason,\n context: this.mergeContext({ context }),\n matchedTargetName: detail.matchedTargetName,\n flagConfigVersion: detail.flagConfigVersion,\n errorDetail: detail.errorDetail,\n evaluationDurationUs: detail.evaluationDurationUs,\n });\n }\n\n identify(context: EvaluationContext): void {\n this.identifiedContext = { ...context };\n }\n\n reset(): void {\n this.identifiedContext = {};\n }\n\n async refresh(): Promise<void> {\n const response = await fetch(\n `${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,\n { headers: { Authorization: `Bearer ${this.apiKey}` } }\n );\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to refresh - ${(error as { error?: string }).error ?? response.statusText}`\n );\n }\n\n this.snapshot = (await response.json()) as EnvironmentSnapshot;\n }\n\n getSnapshot(): EnvironmentSnapshot | null {\n return this.snapshot;\n }\n\n onUpdate(callback: () => void): () => void {\n this.updateListeners.add(callback);\n return () => this.updateListeners.delete(callback);\n }\n\n close(): void {\n if (this.eventBuffer) {\n this.eventBuffer.destroy();\n this.eventBuffer = null;\n }\n }\n}\n\n/**\n * Create a Gradual feature flag client\n *\n * @example\n * ```ts\n * const gradual = createGradual({\n * apiKey: 'gra_xxx',\n * environment: 'production'\n * })\n *\n * // Boolean flags\n * const enabled = await gradual.isEnabled('new-feature')\n *\n * // Typed values (inferred from fallback)\n * const theme = await gradual.get('theme', { fallback: 'dark' })\n *\n * // With user context\n * gradual.identify({ userId: '123', plan: 'pro' })\n * const proFeature = await gradual.isEnabled('pro-feature')\n * ```\n */\nexport function createGradual(options: GradualOptions): Gradual {\n return new GradualClient(options);\n}\n"]}
1
+ {"version":3,"sources":["../src/evaluator.ts","../src/event-buffer.ts","../src/client.ts"],"names":["hashString","str","hash","i","char","getBucketValue","flagKey","context","rollout","bucketKey","seed","hashInput","selectVariationFromRollout","bucketValue","variations","cumulative","matchedRv","rv","variation","evaluateCondition","condition","contextKind","attributeKey","operator","value","contextValue","evaluateConditions","conditions","evaluateSegment","segment","evaluateTarget","target","segments","resolveTargetVariation","resolveDefaultVariation","flag","buildRuleMatchReason","buildRolloutReason","rolloutResult","evaluateFlag","sortedTargets","a","b","resolved","reasons","SDK_VERSION","g","doc","EventBuffer","options","event","batch","payload","DEFAULT_BASE_URL","detectPlatform","nav","win","SDK_PLATFORM","proc","hasHrtime","nowNs","elapsedUs","start","end","GradualClient","pollingEnabled","pollingIntervalMs","previousVersion","cb","error","initResponse","initData","snapshotResponse","merged","allKinds","kind","key","snapshot","startTime","output","err","errorDetail","version","ruleMatch","r","durationUs","params","contextKinds","contextKeys","isAnonymous","result","response","callback","createGradual"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n EvalOutput,\n EvaluationContext,\n Reason,\n SnapshotFlag,\n SnapshotRollout,\n SnapshotRolloutVariation,\n SnapshotRuleCondition,\n SnapshotSegment,\n SnapshotTarget,\n SnapshotVariation,\n} from \"./types\";\n\nfunction hashString(str: string): number {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i);\n // biome-ignore lint/suspicious/noBitwiseOperators: intentional hash algorithm using bitwise shift\n hash = (hash << 5) - hash + char;\n // biome-ignore lint/suspicious/noBitwiseOperators: converting to 32-bit integer\n hash |= 0;\n }\n return Math.abs(hash);\n}\n\nfunction getBucketValue(\n flagKey: string,\n context: EvaluationContext,\n rollout: SnapshotRollout\n): number {\n const bucketKey =\n context[rollout.bucketContextKind]?.[rollout.bucketAttributeKey];\n const seed = rollout.seed ?? \"\";\n const hashInput = `${flagKey}:${seed}:${String(bucketKey ?? \"anonymous\")}`;\n return hashString(hashInput) % 100_000;\n}\n\ninterface RolloutResult {\n variation: SnapshotVariation;\n variationKey: string;\n matchedWeight: number;\n bucketValue: number;\n}\n\nfunction selectVariationFromRollout(\n rollout: SnapshotRollout,\n bucketValue: number,\n variations: Record<string, SnapshotVariation>\n): RolloutResult | undefined {\n let cumulative = 0;\n let matchedRv: SnapshotRolloutVariation | undefined;\n\n for (const rv of rollout.variations) {\n cumulative += rv.weight;\n if (bucketValue < cumulative) {\n matchedRv = rv;\n break;\n }\n }\n\n if (!matchedRv) {\n matchedRv = rollout.variations.at(-1);\n }\n\n if (!matchedRv) {\n return undefined;\n }\n\n const variation = variations[matchedRv.variationKey];\n if (!variation) {\n return undefined;\n }\n\n return {\n variation,\n variationKey: matchedRv.variationKey,\n matchedWeight: matchedRv.weight,\n bucketValue,\n };\n}\n\nfunction evaluateCondition(\n condition: SnapshotRuleCondition,\n context: EvaluationContext\n): boolean {\n const { contextKind, attributeKey, operator, value } = condition;\n const contextValue = context[contextKind]?.[attributeKey];\n\n switch (operator) {\n case \"equals\":\n return contextValue === value;\n\n case \"not_equals\":\n return contextValue !== value;\n\n case \"contains\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.includes(value);\n }\n if (Array.isArray(contextValue)) {\n return contextValue.includes(value);\n }\n return false;\n\n case \"not_contains\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return !contextValue.includes(value);\n }\n if (Array.isArray(contextValue)) {\n return !contextValue.includes(value);\n }\n return true;\n\n case \"starts_with\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.startsWith(value);\n }\n return false;\n\n case \"ends_with\":\n if (typeof contextValue === \"string\" && typeof value === \"string\") {\n return contextValue.endsWith(value);\n }\n return false;\n\n case \"greater_than\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue > value;\n }\n return false;\n\n case \"less_than\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue < value;\n }\n return false;\n\n case \"greater_than_or_equal\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue >= value;\n }\n return false;\n\n case \"less_than_or_equal\":\n if (typeof contextValue === \"number\" && typeof value === \"number\") {\n return contextValue <= value;\n }\n return false;\n\n case \"in\":\n if (Array.isArray(value)) {\n return value.includes(contextValue);\n }\n return false;\n\n case \"not_in\":\n if (Array.isArray(value)) {\n return !value.includes(contextValue);\n }\n return true;\n\n case \"exists\":\n return contextValue !== undefined && contextValue !== null;\n\n case \"not_exists\":\n return contextValue === undefined || contextValue === null;\n\n default:\n return false;\n }\n}\n\nfunction evaluateConditions(\n conditions: SnapshotRuleCondition[],\n context: EvaluationContext\n): boolean {\n return conditions.every((condition) => evaluateCondition(condition, context));\n}\n\nfunction evaluateSegment(\n segment: SnapshotSegment,\n context: EvaluationContext\n): boolean {\n return evaluateConditions(segment.conditions, context);\n}\n\nfunction evaluateTarget(\n target: SnapshotTarget,\n context: EvaluationContext,\n segments: Record<string, SnapshotSegment>\n): boolean {\n switch (target.type) {\n case \"individual\":\n if (\n target.contextKind &&\n target.attributeKey &&\n target.attributeValue !== undefined\n ) {\n return (\n context[target.contextKind]?.[target.attributeKey] ===\n target.attributeValue\n );\n }\n return false;\n\n case \"rule\":\n if (target.conditions) {\n return evaluateConditions(target.conditions, context);\n }\n return false;\n\n case \"segment\":\n if (target.segmentKey) {\n const segment = segments[target.segmentKey];\n if (segment) {\n return evaluateSegment(segment, context);\n }\n }\n return false;\n\n default:\n return false;\n }\n}\n\nfunction resolveTargetVariation(\n target: SnapshotTarget,\n flagKey: string,\n context: EvaluationContext,\n variations: Record<string, SnapshotVariation>\n): RolloutResult | undefined {\n if (target.rollout) {\n const bucketValue = getBucketValue(flagKey, context, target.rollout);\n return selectVariationFromRollout(target.rollout, bucketValue, variations);\n }\n\n if (target.variationKey) {\n const variation = variations[target.variationKey];\n if (variation) {\n return {\n variation,\n variationKey: target.variationKey,\n matchedWeight: 100_000,\n bucketValue: 0,\n };\n }\n }\n\n return undefined;\n}\n\nfunction resolveDefaultVariation(\n flag: SnapshotFlag,\n context: EvaluationContext\n): RolloutResult | undefined {\n if (flag.defaultRollout) {\n const bucketValue = getBucketValue(flag.key, context, flag.defaultRollout);\n return selectVariationFromRollout(\n flag.defaultRollout,\n bucketValue,\n flag.variations\n );\n }\n\n if (flag.defaultVariationKey) {\n const variation = flag.variations[flag.defaultVariationKey];\n if (variation) {\n return {\n variation,\n variationKey: flag.defaultVariationKey,\n matchedWeight: 100_000,\n bucketValue: 0,\n };\n }\n }\n\n return undefined;\n}\n\nfunction buildRuleMatchReason(target: SnapshotTarget): Reason {\n return {\n type: \"rule_match\",\n ruleId: target.id ?? \"\",\n ruleName: target.name,\n };\n}\n\nfunction buildRolloutReason(rolloutResult: RolloutResult): Reason {\n return {\n type: \"percentage_rollout\",\n percentage: rolloutResult.matchedWeight / 1000,\n bucket: rolloutResult.bucketValue,\n };\n}\n\nexport function evaluateFlag(\n flag: SnapshotFlag,\n context: EvaluationContext,\n segments: Record<string, SnapshotSegment>\n): EvalOutput {\n if (!flag.enabled) {\n const offVariation = flag.variations[flag.offVariationKey];\n return {\n value: offVariation?.value,\n variationKey: flag.offVariationKey,\n\n reasons: [{ type: \"off\" }],\n };\n }\n\n const sortedTargets = [...flag.targets].sort(\n (a, b) => a.sortOrder - b.sortOrder\n );\n\n for (const target of sortedTargets) {\n if (evaluateTarget(target, context, segments)) {\n const resolved = resolveTargetVariation(\n target,\n flag.key,\n context,\n flag.variations\n );\n if (resolved) {\n const reasons: Reason[] = [buildRuleMatchReason(target)];\n if (target.rollout) {\n reasons.push(buildRolloutReason(resolved));\n }\n\n return {\n value: resolved.variation.value,\n variationKey: resolved.variationKey,\n\n reasons,\n matchedTargetName: target.name,\n };\n }\n }\n }\n\n const resolved = resolveDefaultVariation(flag, context);\n if (resolved) {\n const reasons: Reason[] = [];\n if (flag.defaultRollout) {\n reasons.push(buildRolloutReason(resolved));\n }\n reasons.push({ type: \"default\" });\n\n return {\n value: resolved.variation.value,\n variationKey: resolved.variationKey,\n\n reasons,\n };\n }\n\n return {\n value: undefined,\n variationKey: undefined,\n\n reasons: [{ type: \"default\" }],\n };\n}\n","import type { EvaluationBatchPayload, EvaluationEvent } from \"./types\";\n\ndeclare const __SDK_VERSION__: string;\nexport const SDK_VERSION = __SDK_VERSION__;\n\ninterface EventBufferOptions {\n baseUrl: string;\n apiKey: string;\n meta: {\n projectId: string;\n organizationId: string;\n environmentId: string;\n sdkPlatform?: string;\n };\n flushIntervalMs: number;\n maxBatchSize: number;\n}\n\nconst g = globalThis as Record<string, unknown>;\nconst doc = g.document as\n | {\n visibilityState?: string;\n addEventListener?: (event: string, handler: () => void) => void;\n removeEventListener?: (event: string, handler: () => void) => void;\n }\n | undefined;\nexport class EventBuffer {\n private readonly events: EvaluationEvent[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private readonly options: EventBufferOptions;\n private readonly onVisibilityChange: (() => void) | null = null;\n\n constructor(options: EventBufferOptions) {\n this.options = options;\n this.timer = setInterval(() => this.flush(), this.options.flushIntervalMs);\n\n if (doc?.addEventListener) {\n this.onVisibilityChange = () => {\n if (doc.visibilityState === \"hidden\") {\n this.flushBeacon();\n }\n };\n doc.addEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n }\n\n push(event: EvaluationEvent): void {\n this.events.push(event);\n if (this.events.length >= this.options.maxBatchSize) {\n this.flush();\n }\n }\n\n private buildPayload(batch: EvaluationEvent[]): EvaluationBatchPayload {\n return {\n meta: {\n ...this.options.meta,\n sdkVersion: SDK_VERSION,\n },\n events: batch,\n };\n }\n\n flush(): void {\n if (this.events.length === 0) {\n return;\n }\n const batch = this.events.splice(0, this.options.maxBatchSize);\n const payload = this.buildPayload(batch);\n\n fetch(`${this.options.baseUrl}/sdk/evaluations`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.options.apiKey}`,\n },\n body: JSON.stringify(payload),\n }).catch(() => {\n // Fire-and-forget: silently drop failed events to prevent unbounded growth\n });\n }\n\n /**\n * Flush with keepalive flag for reliable delivery during page unload.\n * keepalive fetch survives page navigation like sendBeacon but supports headers.\n */\n private flushBeacon(): void {\n if (this.events.length === 0) {\n return;\n }\n\n const batch = this.events.splice(0, this.options.maxBatchSize);\n const payload = this.buildPayload(batch);\n\n fetch(`${this.options.baseUrl}/sdk/evaluations`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.options.apiKey}`,\n },\n body: JSON.stringify(payload),\n keepalive: true,\n }).catch(() => {\n // Fire-and-forget\n });\n }\n\n destroy(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n if (this.onVisibilityChange && doc?.removeEventListener) {\n doc.removeEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n this.flush();\n }\n}\n","import { evaluateFlag } from \"./evaluator\";\nimport { EventBuffer } from \"./event-buffer\";\nimport type {\n EnvironmentSnapshot,\n EvalOutput,\n EvaluationContext,\n EvaluationResult,\n FlagOptions,\n GradualOptions,\n IsEnabledOptions,\n Reason,\n} from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://worker.gradual.so/api/v1\";\n\ntype SdkPlatform = \"browser\" | \"node\" | \"react-native\" | \"edge\" | \"unknown\";\n\nfunction detectPlatform(): SdkPlatform {\n try {\n const g = globalThis as Record<string, unknown>;\n const nav = g.navigator as\n | { product?: string; userAgent?: string }\n | undefined;\n if (nav && nav.product === \"ReactNative\") {\n return \"react-native\";\n }\n const win = g.window as { document?: unknown } | undefined;\n if (win && typeof win.document !== \"undefined\") {\n return \"browser\";\n }\n const proc = g.process as { versions?: { node?: string } } | undefined;\n if (proc?.versions?.node) {\n return \"node\";\n }\n if (typeof globalThis !== \"undefined\") {\n return \"edge\";\n }\n } catch {\n // Ignore detection errors\n }\n return \"unknown\";\n}\n\nconst SDK_PLATFORM = detectPlatform();\n\nconst proc = (globalThis as Record<string, unknown>).process as\n | { hrtime?: { bigint?: () => bigint } }\n | undefined;\nconst hasHrtime = typeof proc?.hrtime?.bigint === \"function\";\n\nfunction nowNs(): bigint | number {\n if (hasHrtime) {\n // biome-ignore lint/style/noNonNullAssertion: guarded by hasHrtime check\n return proc!.hrtime!.bigint!();\n }\n if (typeof performance !== \"undefined\") {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction elapsedUs(start: bigint | number): number {\n const end = nowNs();\n if (typeof start === \"bigint\" && typeof end === \"bigint\") {\n // hrtime bigint: nanoseconds → microseconds\n return Number((end - start) / 1000n);\n }\n // performance.now() ms or Date.now() ms → microseconds\n return Math.round(((end as number) - (start as number)) * 1000);\n}\n\nexport interface Gradual {\n /** Wait for the SDK to be ready (snapshot fetched) */\n ready(): Promise<void>;\n\n /** Check if the SDK is ready for sync access */\n isReady(): boolean;\n\n /** Check if a boolean flag is enabled */\n isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean>;\n\n /** Get a flag value with type inference from fallback */\n get<T>(key: string, options: FlagOptions<T>): Promise<T>;\n\n /** Evaluate a flag and return the full structured result (also tracks the evaluation) */\n evaluate<T = unknown>(\n key: string,\n options?: { context?: EvaluationContext }\n ): Promise<EvaluationResult<T>>;\n\n /** Set persistent user context for all evaluations */\n identify(context: EvaluationContext): void;\n\n /** Clear the identified user context */\n reset(): void;\n\n /** Refresh the snapshot from the server */\n refresh(): Promise<void>;\n\n /** Get the current snapshot (for debugging) */\n getSnapshot(): EnvironmentSnapshot | null;\n\n /** Subscribe to snapshot updates from polling (returns unsubscribe function) */\n onUpdate(callback: () => void): () => void;\n\n /** Flush pending evaluation events and stop the event buffer */\n close(): void;\n\n /** Sync methods (throw if not ready) */\n sync: GradualSync;\n}\n\nexport interface GradualSync {\n /** Sync version of isEnabled (throws if not ready) */\n isEnabled(key: string, options?: IsEnabledOptions): boolean;\n\n /** Sync version of get (throws if not ready) */\n get<T>(key: string, options: FlagOptions<T>): T;\n\n /** Evaluate a flag without tracking. Use with track() for React-safe evaluation. */\n evaluate<T = unknown>(\n key: string,\n options?: { context?: EvaluationContext }\n ): EvaluationResult<T>;\n\n /** Manually track an evaluation that was produced by evaluate(). */\n track(\n key: string,\n result: EvaluationResult,\n context?: EvaluationContext\n ): void;\n}\n\nclass GradualClient implements Gradual {\n private readonly apiKey: string;\n private readonly environment: string;\n private readonly baseUrl: string;\n private readonly initPromise: Promise<void>;\n private snapshot: EnvironmentSnapshot | null = null;\n private identifiedContext: EvaluationContext = {};\n private readonly updateListeners: Set<() => void> = new Set();\n private eventBuffer: EventBuffer | null = null;\n private readonly eventsEnabled: boolean;\n private readonly eventsFlushIntervalMs: number;\n private readonly eventsMaxBatchSize: number;\n\n readonly sync: GradualSync;\n\n constructor(options: GradualOptions) {\n this.apiKey = options.apiKey;\n this.environment = options.environment;\n this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n this.eventsEnabled = options.events?.enabled ?? true;\n this.eventsFlushIntervalMs = options.events?.flushIntervalMs ?? 30_000;\n this.eventsMaxBatchSize = options.events?.maxBatchSize ?? 100;\n this.initPromise = this.init();\n\n this.sync = {\n isEnabled: this.isEnabledSync.bind(this),\n get: this.getSync.bind(this),\n evaluate: this.evaluateSync.bind(this),\n track: this.trackSync.bind(this),\n };\n\n const pollingEnabled = options.polling?.enabled ?? true;\n const pollingIntervalMs = options.polling?.intervalMs ?? 10_000;\n\n if (pollingEnabled) {\n this.initPromise.then(() => {\n setInterval(async () => {\n try {\n const previousVersion = this.snapshot?.version;\n await this.refresh();\n if (this.snapshot && this.snapshot.version !== previousVersion) {\n for (const cb of this.updateListeners) {\n cb();\n }\n }\n } catch (error) {\n console.warn(\"Gradual: Polling refresh failed\", error);\n }\n }, pollingIntervalMs);\n });\n }\n }\n\n private async init(): Promise<void> {\n const initResponse = await fetch(`${this.baseUrl}/sdk/init`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ apiKey: this.apiKey }),\n });\n\n if (!initResponse.ok) {\n const error = await initResponse.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to initialize - ${(error as { error?: string }).error ?? initResponse.statusText}`\n );\n }\n\n const initData = (await initResponse.json()) as {\n valid: boolean;\n error?: string;\n };\n\n if (!initData.valid) {\n throw new Error(\n `Gradual: Invalid API key - ${initData.error ?? \"Unknown error\"}`\n );\n }\n\n const snapshotResponse = await fetch(\n `${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,\n { headers: { Authorization: `Bearer ${this.apiKey}` } }\n );\n\n if (!snapshotResponse.ok) {\n const error = await snapshotResponse.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to fetch snapshot - ${(error as { error?: string }).error ?? snapshotResponse.statusText}`\n );\n }\n\n this.snapshot = (await snapshotResponse.json()) as EnvironmentSnapshot;\n\n if (this.eventsEnabled && this.snapshot.meta) {\n this.eventBuffer = new EventBuffer({\n baseUrl: this.baseUrl,\n apiKey: this.apiKey,\n meta: {\n projectId: this.snapshot.meta.projectId,\n organizationId: this.snapshot.meta.organizationId,\n environmentId: this.snapshot.meta.environmentId,\n sdkPlatform: SDK_PLATFORM,\n },\n flushIntervalMs: this.eventsFlushIntervalMs,\n maxBatchSize: this.eventsMaxBatchSize,\n });\n }\n }\n\n private ensureReady(): EnvironmentSnapshot {\n if (!this.snapshot) {\n throw new Error(\n \"Gradual: SDK not ready. Use await ready() or async methods.\"\n );\n }\n return this.snapshot;\n }\n\n private mergeContext(options?: {\n context?: EvaluationContext;\n }): EvaluationContext {\n const merged: EvaluationContext = {};\n const allKinds = new Set([\n ...Object.keys(this.identifiedContext),\n ...Object.keys(options?.context ?? {}),\n ]);\n for (const kind of allKinds) {\n merged[kind] = {\n ...this.identifiedContext[kind],\n ...options?.context?.[kind],\n };\n }\n return merged;\n }\n\n private evaluateRaw(\n key: string,\n context: EvaluationContext\n ): {\n output: EvalOutput | null;\n snapshot: EnvironmentSnapshot;\n durationUs: number;\n } {\n const snapshot = this.ensureReady();\n if (!snapshot.flags) {\n return { output: null, snapshot, durationUs: 0 };\n }\n const flag = snapshot.flags[key];\n if (!flag) {\n return { output: null, snapshot, durationUs: 0 };\n }\n\n const startTime = nowNs();\n let output: EvalOutput;\n try {\n output = evaluateFlag(flag, context, snapshot.segments ?? {});\n } catch (err) {\n const errorDetail = err instanceof Error ? err.message : String(err);\n output = {\n value: undefined,\n variationKey: undefined,\n reasons: [{ type: \"error\", detail: errorDetail }],\n errorDetail,\n };\n }\n\n return { output, snapshot, durationUs: elapsedUs(startTime) };\n }\n\n private buildResult<T>(\n key: string,\n output: EvalOutput,\n version: number\n ): EvaluationResult<T> {\n const ruleMatch = output.reasons.find(\n (r): r is Extract<Reason, { type: \"rule_match\" }> =>\n r.type === \"rule_match\"\n );\n\n return {\n key,\n value: output.value as T,\n variationKey: output.variationKey,\n reasons: output.reasons,\n ruleId: ruleMatch?.ruleId,\n version,\n evaluatedAt: new Date().toISOString(),\n };\n }\n\n private evaluateAndTrack(key: string, context: EvaluationContext): unknown {\n const { output, snapshot, durationUs } = this.evaluateRaw(key, context);\n\n if (!output) {\n this.trackEvent({\n flagKey: key,\n variationKey: undefined,\n value: undefined,\n reasons: [{ type: \"error\", detail: \"FLAG_NOT_FOUND\" }],\n context,\n flagConfigVersion: snapshot.version,\n });\n return undefined;\n }\n\n this.trackEvent({\n flagKey: key,\n variationKey: output.variationKey,\n value: output.value,\n reasons: output.reasons,\n context,\n matchedTargetName: output.matchedTargetName,\n flagConfigVersion: snapshot.version,\n errorDetail: output.errorDetail,\n evaluationDurationUs: durationUs,\n });\n\n return output.value;\n }\n\n private trackEvent(params: {\n flagKey: string;\n variationKey: string | undefined;\n value: unknown;\n reasons: Reason[];\n evaluatedAt?: string;\n ruleId?: string;\n context: EvaluationContext;\n matchedTargetName?: string;\n flagConfigVersion?: number;\n errorDetail?: string;\n evaluationDurationUs?: number;\n }): void {\n if (!this.eventBuffer) {\n return;\n }\n const { context } = params;\n const contextKinds = Object.keys(context);\n const contextKeys: Record<string, string[]> = {};\n for (const kind of contextKinds) {\n contextKeys[kind] = Object.keys(context[kind] ?? {});\n }\n\n const isAnonymous =\n contextKinds.length === 0 ||\n contextKinds.every(\n (kind) => Object.keys(context[kind] ?? {}).length === 0\n );\n\n this.eventBuffer.push({\n flagKey: params.flagKey,\n variationKey: params.variationKey,\n value: params.value,\n reasons: params.reasons,\n evaluatedAt: params.evaluatedAt,\n ruleId: params.ruleId,\n contextKinds,\n contextKeys,\n timestamp: Date.now(),\n matchedTargetName: params.matchedTargetName,\n flagConfigVersion: params.flagConfigVersion,\n errorDetail: params.errorDetail,\n evaluationDurationUs: params.evaluationDurationUs,\n isAnonymous,\n });\n }\n\n async ready(): Promise<void> {\n await this.initPromise;\n }\n\n isReady(): boolean {\n return this.snapshot !== null;\n }\n\n async isEnabled(key: string, options?: IsEnabledOptions): Promise<boolean> {\n await this.initPromise;\n const value = this.evaluateAndTrack(key, this.mergeContext(options));\n return typeof value === \"boolean\" ? value : false;\n }\n\n async get<T>(key: string, options: FlagOptions<T>): Promise<T> {\n await this.initPromise;\n const value = this.evaluateAndTrack(key, this.mergeContext(options));\n return value !== undefined && value !== null\n ? (value as T)\n : options.fallback;\n }\n\n async evaluate<T = unknown>(\n key: string,\n options?: { context?: EvaluationContext }\n ): Promise<EvaluationResult<T>> {\n await this.initPromise;\n const context = this.mergeContext(options);\n const { output, snapshot, durationUs } = this.evaluateRaw(key, context);\n\n if (!output) {\n const result: EvaluationResult<T> = {\n key,\n value: undefined as T,\n variationKey: undefined,\n reasons: [{ type: \"error\", detail: \"FLAG_NOT_FOUND\" }],\n version: snapshot.version,\n evaluatedAt: new Date().toISOString(),\n };\n this.trackEvent({\n flagKey: key,\n variationKey: undefined,\n value: undefined,\n reasons: result.reasons,\n evaluatedAt: result.evaluatedAt,\n context,\n flagConfigVersion: snapshot.version,\n });\n return result;\n }\n\n const result = this.buildResult<T>(key, output, snapshot.version);\n\n this.trackEvent({\n flagKey: key,\n variationKey: output.variationKey,\n value: output.value,\n reasons: output.reasons,\n evaluatedAt: result.evaluatedAt,\n ruleId: result.ruleId,\n context,\n matchedTargetName: output.matchedTargetName,\n flagConfigVersion: snapshot.version,\n errorDetail: output.errorDetail,\n evaluationDurationUs: durationUs,\n });\n\n return result;\n }\n\n private isEnabledSync(key: string, options?: IsEnabledOptions): boolean {\n const value = this.evaluateAndTrack(key, this.mergeContext(options));\n return typeof value === \"boolean\" ? value : false;\n }\n\n private getSync<T>(key: string, options: FlagOptions<T>): T {\n const value = this.evaluateAndTrack(key, this.mergeContext(options));\n return value !== undefined && value !== null\n ? (value as T)\n : options.fallback;\n }\n\n private evaluateSync<T = unknown>(\n key: string,\n options?: { context?: EvaluationContext }\n ): EvaluationResult<T> {\n const context = this.mergeContext(options);\n const { output, snapshot } = this.evaluateRaw(key, context);\n\n if (!output) {\n return {\n key,\n value: undefined as T,\n variationKey: undefined,\n reasons: [{ type: \"error\", detail: \"FLAG_NOT_FOUND\" }],\n version: snapshot.version,\n evaluatedAt: new Date().toISOString(),\n };\n }\n\n return this.buildResult<T>(key, output, snapshot.version);\n }\n\n private trackSync(\n key: string,\n result: EvaluationResult,\n context?: EvaluationContext\n ): void {\n const ruleMatch = result.reasons.find(\n (r): r is Extract<Reason, { type: \"rule_match\" }> =>\n r.type === \"rule_match\"\n );\n\n this.trackEvent({\n flagKey: key,\n variationKey: result.variationKey,\n value: result.value,\n reasons: result.reasons,\n evaluatedAt: result.evaluatedAt,\n ruleId: result.ruleId,\n context: this.mergeContext({ context }),\n matchedTargetName: ruleMatch?.ruleName,\n flagConfigVersion: result.version,\n });\n }\n\n identify(context: EvaluationContext): void {\n this.identifiedContext = { ...context };\n }\n\n reset(): void {\n this.identifiedContext = {};\n }\n\n async refresh(): Promise<void> {\n const response = await fetch(\n `${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,\n { headers: { Authorization: `Bearer ${this.apiKey}` } }\n );\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(\n `Gradual: Failed to refresh - ${(error as { error?: string }).error ?? response.statusText}`\n );\n }\n\n this.snapshot = (await response.json()) as EnvironmentSnapshot;\n }\n\n getSnapshot(): EnvironmentSnapshot | null {\n return this.snapshot;\n }\n\n onUpdate(callback: () => void): () => void {\n this.updateListeners.add(callback);\n return () => this.updateListeners.delete(callback);\n }\n\n close(): void {\n if (this.eventBuffer) {\n this.eventBuffer.destroy();\n this.eventBuffer = null;\n }\n }\n}\n\n/**\n * Create a Gradual feature flag client\n *\n * @example\n * ```ts\n * const gradual = createGradual({\n * apiKey: 'gra_xxx',\n * environment: 'production'\n * })\n *\n * // Boolean flags\n * const enabled = await gradual.isEnabled('new-feature')\n *\n * // Typed values (inferred from fallback)\n * const theme = await gradual.get('theme', { fallback: 'dark' })\n *\n * // Full structured result\n * const result = await gradual.evaluate('new-feature')\n * // result.value, result.reasons, result.ruleId, result.version\n *\n * // With user context\n * gradual.identify({ userId: '123', plan: 'pro' })\n * const proFeature = await gradual.isEnabled('pro-feature')\n * ```\n */\nexport function createGradual(options: GradualOptions): Gradual {\n return new GradualClient(options);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gradual-so/sdk",
3
- "version": "0.7.5",
3
+ "version": "0.8.0",
4
4
  "description": "Gradual feature flag SDK for TypeScript and JavaScript",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",