@gradual-so/sdk 0.7.2 → 0.7.3
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 +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
'use strict';function E(t){let e=0;for(let n=0;n<t.length;n++){let i=t.charCodeAt(n);e=(e<<5)-e+i,e|=0;}return Math.abs(e)}function c(t,e,n){let i=e[n.bucketContextKind]?.[n.bucketAttributeKey],r=n.seed??"",o=`${t}:${r}:${String(i??"anonymous")}`;return E(o)%1e5}function f(t,e,n){let i=0;for(let o of t.variations)if(i+=o.weight,e<i)return n[o.variationKey];let r=t.variations.at(-1);return r?n[r.variationKey]:void 0}function S(t,e){let{contextKind:n,attributeKey:i,operator:r,value:o}=t,a=e[n]?.[i];switch(r){case "equals":return a===o;case "not_equals":return a!==o;case "contains":return typeof a=="string"&&typeof o=="string"||Array.isArray(a)?a.includes(o):false;case "not_contains":return typeof a=="string"&&typeof o=="string"||Array.isArray(a)?!a.includes(o):true;case "starts_with":return typeof a=="string"&&typeof o=="string"?a.startsWith(o):false;case "ends_with":return typeof a=="string"&&typeof o=="string"?a.endsWith(o):false;case "greater_than":return typeof a=="number"&&typeof o=="number"?a>o:false;case "less_than":return typeof a=="number"&&typeof o=="number"?a<o:false;case "greater_than_or_equal":return typeof a=="number"&&typeof o=="number"?a>=o:false;case "less_than_or_equal":return typeof a=="number"&&typeof o=="number"?a<=o:false;case "in":return Array.isArray(o)?o.includes(a):false;case "not_in":return Array.isArray(o)?!o.includes(a):true;case "exists":return a!=null;case "not_exists":return a==null;default:return false}}function p(t,e){return t.every(n=>S(n,e))}function K(t,e){return p(t.conditions,e)}function x(t,e,n){switch(t.type){case "individual":return t.contextKind&&t.attributeKey&&t.attributeValue!==void 0?e[t.contextKind]?.[t.attributeKey]===t.attributeValue:false;case "rule":return t.conditions?p(t.conditions,e):false;case "segment":if(t.segmentKey){let i=n[t.segmentKey];if(i)return K(i,e)}return false;default:return false}}function w(t,e,n,i){if(t.rollout){let r=c(e,n,t.rollout),o=f(t.rollout,r,i);if(o){let a=Object.keys(i).find(l=>i[l]===o);return a?{variation:o,variationKey:a}:void 0}return}if(t.variationKey){let r=i[t.variationKey];return r?{variation:r,variationKey:t.variationKey}:void 0}}function T(t,e){if(t.defaultRollout){let n=c(t.key,e,t.defaultRollout),i=f(t.defaultRollout,n,t.variations);if(i){let r=Object.keys(t.variations).find(o=>t.variations[o]===i);return r?{variation:i,variationKey:r}:void 0}return}if(t.defaultVariationKey){let n=t.variations[t.defaultVariationKey];return n?{variation:n,variationKey:t.defaultVariationKey}:void 0}}function h(t,e,n){if(!t.enabled)return {value:t.variations[t.offVariationKey]?.value,variationKey:t.offVariationKey,reason:"FLAG_DISABLED"};let i=[...t.targets].sort((o,a)=>o.sortOrder-a.sortOrder);for(let o of i)if(x(o,e,n)){let a=w(o,t.key,e,t.variations);if(a)return {value:a.variation.value,variationKey:a.variationKey,reason:"TARGET_MATCH",matchedTargetName:o.name}}let r=T(t,e);return r?{value:r.variation.value,variationKey:r.variationKey,reason:t.defaultRollout?"DEFAULT_ROLLOUT":"DEFAULT_VARIATION"}:{value:void 0,variationKey:void 0,reason:"DEFAULT_VARIATION"}}var R="0.6.1",g=globalThis,s=g.document,y=g.navigator,u=class{events=[];timer=null;options;onVisibilityChange=null;constructor(e){this.options=e,this.timer=setInterval(()=>this.flush(),this.options.flushIntervalMs),s?.addEventListener&&(this.onVisibilityChange=()=>{s.visibilityState==="hidden"&&this.flushBeacon();},s.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),n=this.buildPayload(e);fetch(`${this.options.baseUrl}/sdk/evaluations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`},body:JSON.stringify(n)}).catch(()=>{});}flushBeacon(){if(this.events.length===0)return;if(!y?.sendBeacon){this.flush();return}let e=this.events.splice(0,this.options.maxBatchSize),n=this.buildPayload(e),i=new Blob([JSON.stringify(n)],{type:"application/json"});y.sendBeacon(`${this.options.baseUrl}/sdk/evaluations?key=${this.options.apiKey}`,i)||(this.events.unshift(...e),this.flush());}destroy(){this.timer&&(clearInterval(this.timer),this.timer=null),this.onVisibilityChange&&s?.removeEventListener&&s.removeEventListener("visibilitychange",this.onVisibilityChange),this.flush();}};var k="https://worker.gradual.so/api/v1";function C(){try{let t=globalThis,e=t.navigator;if(e&&e.product==="ReactNative")return "react-native";let n=t.window;if(n&&typeof n.document<"u")return "browser";if(t.process?.versions?.node)return "node";if(typeof globalThis<"u")return "edge"}catch{}return "unknown"}var O=C(),m=globalThis.process,V=typeof m?.hrtime?.bigint=="function";function b(){return V?m.hrtime.bigint():typeof performance<"u"?performance.now():Date.now()}function I(t){let e=b();return typeof t=="bigint"&&typeof e=="bigint"?Number((e-t)/1000n):Math.round((e-t)*1e3)}var v=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??k,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)};let n=e.polling?.enabled??true,i=e.polling?.intervalMs??1e4;n&&this.initPromise.then(()=>{setInterval(async()=>{try{let r=this.snapshot?.version;if(await this.refresh(),this.snapshot&&this.snapshot.version!==r)for(let o of this.updateListeners)o();}catch(r){console.warn("Gradual: Polling refresh failed",r);}},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 r=await e.json().catch(()=>({}));throw new Error(`Gradual: Failed to initialize - ${r.error??e.statusText}`)}let n=await e.json();if(!n.valid)throw new Error(`Gradual: Invalid API key - ${n.error??"Unknown error"}`);let i=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!i.ok){let r=await i.json().catch(()=>({}));throw new Error(`Gradual: Failed to fetch snapshot - ${r.error??i.statusText}`)}this.snapshot=await i.json(),this.eventsEnabled&&this.snapshot.meta&&(this.eventBuffer=new u({baseUrl:this.baseUrl,apiKey:this.apiKey,meta:{projectId:this.snapshot.meta.projectId,organizationId:this.snapshot.meta.organizationId,environmentId:this.snapshot.meta.environmentId,sdkPlatform:O},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 n={},i=new Set([...Object.keys(this.identifiedContext),...Object.keys(e?.context??{})]);for(let r of i)n[r]={...this.identifiedContext[r],...e?.context?.[r]};return n}evaluate(e,n){let i=this.ensureReady();if(!i.flags)return;let r=i.flags[e];if(!r){this.trackEvent({flagKey:e,variationKey:void 0,value:void 0,reason:"FLAG_NOT_FOUND",context:n,flagConfigVersion:i.version});return}let o=b(),a;try{a=h(r,n,i.segments??{});}catch(d){a={value:void 0,variationKey:void 0,reason:"ERROR",errorDetail:d instanceof Error?d.message:String(d)};}let l=I(o);return this.trackEvent({flagKey:e,variationKey:a.variationKey,value:a.value,reason:a.reason,context:n,matchedTargetName:a.matchedTargetName,flagConfigVersion:i.version,errorDetail:a.errorDetail,evaluationDurationUs:l}),a.value}trackEvent(e){if(!this.eventBuffer)return;let{context:n}=e,i=Object.keys(n),r={};for(let a of i)r[a]=Object.keys(n[a]??{});let o=i.length===0||i.every(a=>Object.keys(n[a]??{}).length===0);this.eventBuffer.push({flagKey:e.flagKey,variationKey:e.variationKey,value:e.value,reason:e.reason,contextKinds:i,contextKeys:r,timestamp:Date.now(),matchedTargetName:e.matchedTargetName,flagConfigVersion:e.flagConfigVersion,errorDetail:e.errorDetail,evaluationDurationUs:e.evaluationDurationUs,isAnonymous:o});}async ready(){await this.initPromise;}isReady(){return this.snapshot!==null}async isEnabled(e,n){await this.initPromise;let i=this.evaluate(e,this.mergeContext(n));return typeof i=="boolean"?i:false}async get(e,n){await this.initPromise;let i=this.evaluate(e,this.mergeContext(n));return i??n.fallback}isEnabledSync(e,n){let i=this.evaluate(e,this.mergeContext(n));return typeof i=="boolean"?i:false}getSync(e,n){let i=this.evaluate(e,this.mergeContext(n));return i??n.fallback}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 n=await e.json().catch(()=>({}));throw new Error(`Gradual: Failed to refresh - ${n.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 B(t){return new v(t)}
|
|
2
|
-
exports.createGradual=B;exports.evaluateFlag=
|
|
1
|
+
'use strict';function x(i){let e=0;for(let t=0;t<i.length;t++){let n=i.charCodeAt(t);e=(e<<5)-e+n,e|=0;}return Math.abs(e)}function f(i,e,t){let n=e[t.bucketContextKind]?.[t.bucketAttributeKey],o=t.seed??"",r=`${i}:${o}:${String(n??"anonymous")}`;return x(r)%1e5}function p(i,e,t){let n=0;for(let r of i.variations)if(n+=r.weight,e<n)return t[r.variationKey];let o=i.variations.at(-1);return o?t[o.variationKey]:void 0}function K(i,e){let{contextKind:t,attributeKey:n,operator:o,value:r}=i,a=e[t]?.[n];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(i,e){return i.every(t=>K(t,e))}function C(i,e){return y(i.conditions,e)}function T(i,e,t){switch(i.type){case "individual":return i.contextKind&&i.attributeKey&&i.attributeValue!==void 0?e[i.contextKind]?.[i.attributeKey]===i.attributeValue:false;case "rule":return i.conditions?y(i.conditions,e):false;case "segment":if(i.segmentKey){let n=t[i.segmentKey];if(n)return C(n,e)}return false;default:return false}}function k(i,e,t,n){if(i.rollout){let o=f(e,t,i.rollout),r=p(i.rollout,o,n);if(r){let a=Object.keys(n).find(s=>n[s]===r);return a?{variation:r,variationKey:a}:void 0}return}if(i.variationKey){let o=n[i.variationKey];return o?{variation:o,variationKey:i.variationKey}:void 0}}function R(i,e){if(i.defaultRollout){let t=f(i.key,e,i.defaultRollout),n=p(i.defaultRollout,t,i.variations);if(n){let o=Object.keys(i.variations).find(r=>i.variations[r]===n);return o?{variation:n,variationKey:o}:void 0}return}if(i.defaultVariationKey){let t=i.variations[i.defaultVariationKey];return t?{variation:t,variationKey:i.defaultVariationKey}:void 0}}function d(i,e,t){if(!i.enabled)return {value:i.variations[i.offVariationKey]?.value,variationKey:i.offVariationKey,reason:"FLAG_DISABLED"};let n=[...i.targets].sort((r,a)=>r.sortOrder-a.sortOrder);for(let r of n)if(T(r,e,t)){let a=k(r,i.key,e,i.variations);if(a)return {value:a.variation.value,variationKey:a.variationKey,reason:"TARGET_MATCH",matchedTargetName:r.name}}let o=R(i,e);return o?{value:o.variation.value,variationKey:o.variationKey,reason:i.defaultRollout?"DEFAULT_ROLLOUT":"DEFAULT_VARIATION"}:{value:void 0,variationKey:void 0,reason:"DEFAULT_VARIATION"}}var w="0.6.1",m=globalThis,u=m.document,g=m.navigator,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:w},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;if(!g?.sendBeacon){this.flush();return}let e=this.events.splice(0,this.options.maxBatchSize),t=this.buildPayload(e),n=new Blob([JSON.stringify(t)],{type:"application/json"});g.sendBeacon(`${this.options.baseUrl}/sdk/evaluations?key=${this.options.apiKey}`,n)||(this.events.unshift(...e),this.flush());}destroy(){this.timer&&(clearInterval(this.timer),this.timer=null),this.onVisibilityChange&&u?.removeEventListener&&u.removeEventListener("visibilitychange",this.onVisibilityChange),this.flush();}};var O="https://worker.gradual.so/api/v1";function V(){try{let i=globalThis,e=i.navigator;if(e&&e.product==="ReactNative")return "react-native";let t=i.window;if(t&&typeof t.document<"u")return "browser";if(i.process?.versions?.node)return "node";if(typeof globalThis<"u")return "edge"}catch{}return "unknown"}var D=V(),E=globalThis.process,I=typeof E?.hrtime?.bigint=="function";function h(){return I?E.hrtime.bigint():typeof performance<"u"?performance.now():Date.now()}function b(i){let e=h();return typeof i=="bigint"&&typeof e=="bigint"?Number((e-i)/1000n):Math.round((e-i)*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??O,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,n=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);}},n);});}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 n=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!n.ok){let o=await n.json().catch(()=>({}));throw new Error(`Gradual: Failed to fetch snapshot - ${o.error??n.statusText}`)}this.snapshot=await n.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:D},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={},n=new Set([...Object.keys(this.identifiedContext),...Object.keys(e?.context??{})]);for(let o of n)t[o]={...this.identifiedContext[o],...e?.context?.[o]};return t}evaluate(e,t){let n=this.ensureReady();if(!n.flags)return;let o=n.flags[e];if(!o){this.trackEvent({flagKey:e,variationKey:void 0,value:void 0,reason:"FLAG_NOT_FOUND",context:t,flagConfigVersion:n.version});return}let r=h(),a;try{a=d(o,t,n.segments??{});}catch(l){a={value:void 0,variationKey:void 0,reason:"ERROR",errorDetail:l instanceof Error?l.message:String(l)};}let s=b(r);return this.trackEvent({flagKey:e,variationKey:a.variationKey,value:a.value,reason:a.reason,context:t,matchedTargetName:a.matchedTargetName,flagConfigVersion:n.version,errorDetail:a.errorDetail,evaluationDurationUs:s}),a.value}trackEvent(e){if(!this.eventBuffer)return;let{context:t}=e,n=Object.keys(t),o={};for(let a of n)o[a]=Object.keys(t[a]??{});let r=n.length===0||n.every(a=>Object.keys(t[a]??{}).length===0);this.eventBuffer.push({flagKey:e.flagKey,variationKey:e.variationKey,value:e.value,reason:e.reason,contextKinds:n,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 n=this.evaluate(e,this.mergeContext(t));return typeof n=="boolean"?n:false}async get(e,t){await this.initPromise;let n=this.evaluate(e,this.mergeContext(t));return n??t.fallback}isEnabledSync(e,t){let n=this.evaluate(e,this.mergeContext(t));return typeof n=="boolean"?n:false}getSync(e,t){let n=this.evaluate(e,this.mergeContext(t));return n??t.fallback}evaluateSync(e,t){let n=this.ensureReady(),o=this.mergeContext(t);if(!n.flags)return {value:void 0,variationKey:void 0,reason:"FLAG_NOT_FOUND",flagConfigVersion:n.version};let r=n.flags[e];if(!r)return {value:void 0,variationKey:void 0,reason:"FLAG_NOT_FOUND",flagConfigVersion:n.version};let a=h(),s;try{s=d(r,o,n.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:b(a),flagConfigVersion:n.version}}trackSync(e,t,n){this.trackEvent({flagKey:e,variationKey:t.variationKey,value:t.value,reason:t.reason,context:this.mergeContext({context:n}),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 B(i){return new c(i)}
|
|
2
|
+
exports.createGradual=B;exports.evaluateFlag=d;//# sourceMappingURL=index.cjs.map
|
|
3
3
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.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","doc","nav","EventBuffer","options","event","batch","payload","blob","DEFAULT_BASE_URL","detectPlatform","g","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","response","callback","createGradual"],"mappings":"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","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\nexport const SDK_VERSION = \"0.6.1\";\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;\nconst nav = g.navigator as\n | { sendBeacon?: (url: string, data: Blob) => boolean }\n | undefined;\n\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 using sendBeacon for reliable delivery during page unload.\n * Falls back to regular flush if sendBeacon is unavailable.\n */\n private flushBeacon(): void {\n if (this.events.length === 0) {\n return;\n }\n\n if (!nav?.sendBeacon) {\n this.flush();\n return;\n }\n\n const batch = this.events.splice(0, this.options.maxBatchSize);\n const payload = this.buildPayload(batch);\n const blob = new Blob([JSON.stringify(payload)], {\n type: \"application/json\",\n });\n\n const sent = nav.sendBeacon(\n `${this.options.baseUrl}/sdk/evaluations?key=${this.options.apiKey}`,\n blob\n );\n\n if (!sent) {\n // sendBeacon failed (e.g. payload too large), put events back\n this.events.unshift(...batch);\n this.flush();\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 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\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 };\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 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","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","nav","EventBuffer","options","event","batch","payload","blob","DEFAULT_BASE_URL","detectPlatform","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":"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","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\nexport const SDK_VERSION = \"0.6.1\";\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;\nconst nav = g.navigator as\n | { sendBeacon?: (url: string, data: Blob) => boolean }\n | undefined;\n\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 using sendBeacon for reliable delivery during page unload.\n * Falls back to regular flush if sendBeacon is unavailable.\n */\n private flushBeacon(): void {\n if (this.events.length === 0) {\n return;\n }\n\n if (!nav?.sendBeacon) {\n this.flush();\n return;\n }\n\n const batch = this.events.splice(0, this.options.maxBatchSize);\n const payload = this.buildPayload(batch);\n const blob = new Blob([JSON.stringify(payload)], {\n type: \"application/json\",\n });\n\n const sent = nav.sendBeacon(\n `${this.options.baseUrl}/sdk/evaluations?key=${this.options.apiKey}`,\n blob\n );\n\n if (!sent) {\n // sendBeacon failed (e.g. payload too large), put events back\n this.events.unshift(...batch);\n this.flush();\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"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -140,11 +140,26 @@ interface Gradual {
|
|
|
140
140
|
/** Sync methods (throw if not ready) */
|
|
141
141
|
sync: GradualSync;
|
|
142
142
|
}
|
|
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
|
+
}
|
|
143
152
|
interface GradualSync {
|
|
144
153
|
/** Sync version of isEnabled (throws if not ready) */
|
|
145
154
|
isEnabled(key: string, options?: IsEnabledOptions): boolean;
|
|
146
155
|
/** Sync version of get (throws if not ready) */
|
|
147
156
|
get<T>(key: string, options: FlagOptions<T>): T;
|
|
157
|
+
/** Evaluate a flag without tracking. Use with track() for React-safe evaluation. */
|
|
158
|
+
evaluate(key: string, options?: {
|
|
159
|
+
context?: EvaluationContext;
|
|
160
|
+
}): EvalDetail;
|
|
161
|
+
/** Manually track an evaluation that was produced by evaluate(). */
|
|
162
|
+
track(key: string, detail: EvalDetail, context?: EvaluationContext): void;
|
|
148
163
|
}
|
|
149
164
|
/**
|
|
150
165
|
* Create a Gradual feature flag client
|
|
@@ -171,4 +186,4 @@ declare function createGradual(options: GradualOptions): Gradual;
|
|
|
171
186
|
|
|
172
187
|
declare function evaluateFlag(flag: SnapshotFlag, context: EvaluationContext, segments: Record<string, SnapshotSegment>): EvaluationResult;
|
|
173
188
|
|
|
174
|
-
export { type EnvironmentSnapshot, 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 };
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -140,11 +140,26 @@ interface Gradual {
|
|
|
140
140
|
/** Sync methods (throw if not ready) */
|
|
141
141
|
sync: GradualSync;
|
|
142
142
|
}
|
|
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
|
+
}
|
|
143
152
|
interface GradualSync {
|
|
144
153
|
/** Sync version of isEnabled (throws if not ready) */
|
|
145
154
|
isEnabled(key: string, options?: IsEnabledOptions): boolean;
|
|
146
155
|
/** Sync version of get (throws if not ready) */
|
|
147
156
|
get<T>(key: string, options: FlagOptions<T>): T;
|
|
157
|
+
/** Evaluate a flag without tracking. Use with track() for React-safe evaluation. */
|
|
158
|
+
evaluate(key: string, options?: {
|
|
159
|
+
context?: EvaluationContext;
|
|
160
|
+
}): EvalDetail;
|
|
161
|
+
/** Manually track an evaluation that was produced by evaluate(). */
|
|
162
|
+
track(key: string, detail: EvalDetail, context?: EvaluationContext): void;
|
|
148
163
|
}
|
|
149
164
|
/**
|
|
150
165
|
* Create a Gradual feature flag client
|
|
@@ -171,4 +186,4 @@ declare function createGradual(options: GradualOptions): Gradual;
|
|
|
171
186
|
|
|
172
187
|
declare function evaluateFlag(flag: SnapshotFlag, context: EvaluationContext, segments: Record<string, SnapshotSegment>): EvaluationResult;
|
|
173
188
|
|
|
174
|
-
export { type EnvironmentSnapshot, 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 };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
function E(t){let e=0;for(let n=0;n<t.length;n++){let i=t.charCodeAt(n);e=(e<<5)-e+i,e|=0;}return Math.abs(e)}function c(t,e,n){let i=e[n.bucketContextKind]?.[n.bucketAttributeKey],r=n.seed??"",o=`${t}:${r}:${String(i??"anonymous")}`;return E(o)%1e5}function f(t,e,n){let i=0;for(let o of t.variations)if(i+=o.weight,e<i)return n[o.variationKey];let r=t.variations.at(-1);return r?n[r.variationKey]:void 0}function S(t,e){let{contextKind:n,attributeKey:i,operator:r,value:o}=t,a=e[n]?.[i];switch(r){case "equals":return a===o;case "not_equals":return a!==o;case "contains":return typeof a=="string"&&typeof o=="string"||Array.isArray(a)?a.includes(o):false;case "not_contains":return typeof a=="string"&&typeof o=="string"||Array.isArray(a)?!a.includes(o):true;case "starts_with":return typeof a=="string"&&typeof o=="string"?a.startsWith(o):false;case "ends_with":return typeof a=="string"&&typeof o=="string"?a.endsWith(o):false;case "greater_than":return typeof a=="number"&&typeof o=="number"?a>o:false;case "less_than":return typeof a=="number"&&typeof o=="number"?a<o:false;case "greater_than_or_equal":return typeof a=="number"&&typeof o=="number"?a>=o:false;case "less_than_or_equal":return typeof a=="number"&&typeof o=="number"?a<=o:false;case "in":return Array.isArray(o)?o.includes(a):false;case "not_in":return Array.isArray(o)?!o.includes(a):true;case "exists":return a!=null;case "not_exists":return a==null;default:return false}}function p(t,e){return t.every(n=>S(n,e))}function K(t,e){return p(t.conditions,e)}function x(t,e,n){switch(t.type){case "individual":return t.contextKind&&t.attributeKey&&t.attributeValue!==void 0?e[t.contextKind]?.[t.attributeKey]===t.attributeValue:false;case "rule":return t.conditions?p(t.conditions,e):false;case "segment":if(t.segmentKey){let i=n[t.segmentKey];if(i)return K(i,e)}return false;default:return false}}function w(t,e,n,i){if(t.rollout){let r=c(e,n,t.rollout),o=f(t.rollout,r,i);if(o){let a=Object.keys(i).find(l=>i[l]===o);return a?{variation:o,variationKey:a}:void 0}return}if(t.variationKey){let r=i[t.variationKey];return r?{variation:r,variationKey:t.variationKey}:void 0}}function T(t,e){if(t.defaultRollout){let n=c(t.key,e,t.defaultRollout),i=f(t.defaultRollout,n,t.variations);if(i){let r=Object.keys(t.variations).find(o=>t.variations[o]===i);return r?{variation:i,variationKey:r}:void 0}return}if(t.defaultVariationKey){let n=t.variations[t.defaultVariationKey];return n?{variation:n,variationKey:t.defaultVariationKey}:void 0}}function h(t,e,n){if(!t.enabled)return {value:t.variations[t.offVariationKey]?.value,variationKey:t.offVariationKey,reason:"FLAG_DISABLED"};let i=[...t.targets].sort((o,a)=>o.sortOrder-a.sortOrder);for(let o of i)if(x(o,e,n)){let a=w(o,t.key,e,t.variations);if(a)return {value:a.variation.value,variationKey:a.variationKey,reason:"TARGET_MATCH",matchedTargetName:o.name}}let r=T(t,e);return r?{value:r.variation.value,variationKey:r.variationKey,reason:t.defaultRollout?"DEFAULT_ROLLOUT":"DEFAULT_VARIATION"}:{value:void 0,variationKey:void 0,reason:"DEFAULT_VARIATION"}}var R="0.6.1",g=globalThis,s=g.document,y=g.navigator,u=class{events=[];timer=null;options;onVisibilityChange=null;constructor(e){this.options=e,this.timer=setInterval(()=>this.flush(),this.options.flushIntervalMs),s?.addEventListener&&(this.onVisibilityChange=()=>{s.visibilityState==="hidden"&&this.flushBeacon();},s.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),n=this.buildPayload(e);fetch(`${this.options.baseUrl}/sdk/evaluations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`},body:JSON.stringify(n)}).catch(()=>{});}flushBeacon(){if(this.events.length===0)return;if(!y?.sendBeacon){this.flush();return}let e=this.events.splice(0,this.options.maxBatchSize),n=this.buildPayload(e),i=new Blob([JSON.stringify(n)],{type:"application/json"});y.sendBeacon(`${this.options.baseUrl}/sdk/evaluations?key=${this.options.apiKey}`,i)||(this.events.unshift(...e),this.flush());}destroy(){this.timer&&(clearInterval(this.timer),this.timer=null),this.onVisibilityChange&&s?.removeEventListener&&s.removeEventListener("visibilitychange",this.onVisibilityChange),this.flush();}};var k="https://worker.gradual.so/api/v1";function C(){try{let t=globalThis,e=t.navigator;if(e&&e.product==="ReactNative")return "react-native";let n=t.window;if(n&&typeof n.document<"u")return "browser";if(t.process?.versions?.node)return "node";if(typeof globalThis<"u")return "edge"}catch{}return "unknown"}var O=C(),m=globalThis.process,V=typeof m?.hrtime?.bigint=="function";function b(){return V?m.hrtime.bigint():typeof performance<"u"?performance.now():Date.now()}function I(t){let e=b();return typeof t=="bigint"&&typeof e=="bigint"?Number((e-t)/1000n):Math.round((e-t)*1e3)}var v=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??k,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)};let n=e.polling?.enabled??true,i=e.polling?.intervalMs??1e4;n&&this.initPromise.then(()=>{setInterval(async()=>{try{let r=this.snapshot?.version;if(await this.refresh(),this.snapshot&&this.snapshot.version!==r)for(let o of this.updateListeners)o();}catch(r){console.warn("Gradual: Polling refresh failed",r);}},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 r=await e.json().catch(()=>({}));throw new Error(`Gradual: Failed to initialize - ${r.error??e.statusText}`)}let n=await e.json();if(!n.valid)throw new Error(`Gradual: Invalid API key - ${n.error??"Unknown error"}`);let i=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!i.ok){let r=await i.json().catch(()=>({}));throw new Error(`Gradual: Failed to fetch snapshot - ${r.error??i.statusText}`)}this.snapshot=await i.json(),this.eventsEnabled&&this.snapshot.meta&&(this.eventBuffer=new u({baseUrl:this.baseUrl,apiKey:this.apiKey,meta:{projectId:this.snapshot.meta.projectId,organizationId:this.snapshot.meta.organizationId,environmentId:this.snapshot.meta.environmentId,sdkPlatform:O},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 n={},i=new Set([...Object.keys(this.identifiedContext),...Object.keys(e?.context??{})]);for(let r of i)n[r]={...this.identifiedContext[r],...e?.context?.[r]};return n}evaluate(e,n){let i=this.ensureReady();if(!i.flags)return;let r=i.flags[e];if(!r){this.trackEvent({flagKey:e,variationKey:void 0,value:void 0,reason:"FLAG_NOT_FOUND",context:n,flagConfigVersion:i.version});return}let o=b(),a;try{a=h(r,n,i.segments??{});}catch(d){a={value:void 0,variationKey:void 0,reason:"ERROR",errorDetail:d instanceof Error?d.message:String(d)};}let l=I(o);return this.trackEvent({flagKey:e,variationKey:a.variationKey,value:a.value,reason:a.reason,context:n,matchedTargetName:a.matchedTargetName,flagConfigVersion:i.version,errorDetail:a.errorDetail,evaluationDurationUs:l}),a.value}trackEvent(e){if(!this.eventBuffer)return;let{context:n}=e,i=Object.keys(n),r={};for(let a of i)r[a]=Object.keys(n[a]??{});let o=i.length===0||i.every(a=>Object.keys(n[a]??{}).length===0);this.eventBuffer.push({flagKey:e.flagKey,variationKey:e.variationKey,value:e.value,reason:e.reason,contextKinds:i,contextKeys:r,timestamp:Date.now(),matchedTargetName:e.matchedTargetName,flagConfigVersion:e.flagConfigVersion,errorDetail:e.errorDetail,evaluationDurationUs:e.evaluationDurationUs,isAnonymous:o});}async ready(){await this.initPromise;}isReady(){return this.snapshot!==null}async isEnabled(e,n){await this.initPromise;let i=this.evaluate(e,this.mergeContext(n));return typeof i=="boolean"?i:false}async get(e,n){await this.initPromise;let i=this.evaluate(e,this.mergeContext(n));return i??n.fallback}isEnabledSync(e,n){let i=this.evaluate(e,this.mergeContext(n));return typeof i=="boolean"?i:false}getSync(e,n){let i=this.evaluate(e,this.mergeContext(n));return i??n.fallback}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 n=await e.json().catch(()=>({}));throw new Error(`Gradual: Failed to refresh - ${n.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 B(t){return new v(t)}
|
|
2
|
-
export{B as createGradual,
|
|
1
|
+
function x(i){let e=0;for(let t=0;t<i.length;t++){let n=i.charCodeAt(t);e=(e<<5)-e+n,e|=0;}return Math.abs(e)}function f(i,e,t){let n=e[t.bucketContextKind]?.[t.bucketAttributeKey],o=t.seed??"",r=`${i}:${o}:${String(n??"anonymous")}`;return x(r)%1e5}function p(i,e,t){let n=0;for(let r of i.variations)if(n+=r.weight,e<n)return t[r.variationKey];let o=i.variations.at(-1);return o?t[o.variationKey]:void 0}function K(i,e){let{contextKind:t,attributeKey:n,operator:o,value:r}=i,a=e[t]?.[n];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(i,e){return i.every(t=>K(t,e))}function C(i,e){return y(i.conditions,e)}function T(i,e,t){switch(i.type){case "individual":return i.contextKind&&i.attributeKey&&i.attributeValue!==void 0?e[i.contextKind]?.[i.attributeKey]===i.attributeValue:false;case "rule":return i.conditions?y(i.conditions,e):false;case "segment":if(i.segmentKey){let n=t[i.segmentKey];if(n)return C(n,e)}return false;default:return false}}function k(i,e,t,n){if(i.rollout){let o=f(e,t,i.rollout),r=p(i.rollout,o,n);if(r){let a=Object.keys(n).find(s=>n[s]===r);return a?{variation:r,variationKey:a}:void 0}return}if(i.variationKey){let o=n[i.variationKey];return o?{variation:o,variationKey:i.variationKey}:void 0}}function R(i,e){if(i.defaultRollout){let t=f(i.key,e,i.defaultRollout),n=p(i.defaultRollout,t,i.variations);if(n){let o=Object.keys(i.variations).find(r=>i.variations[r]===n);return o?{variation:n,variationKey:o}:void 0}return}if(i.defaultVariationKey){let t=i.variations[i.defaultVariationKey];return t?{variation:t,variationKey:i.defaultVariationKey}:void 0}}function d(i,e,t){if(!i.enabled)return {value:i.variations[i.offVariationKey]?.value,variationKey:i.offVariationKey,reason:"FLAG_DISABLED"};let n=[...i.targets].sort((r,a)=>r.sortOrder-a.sortOrder);for(let r of n)if(T(r,e,t)){let a=k(r,i.key,e,i.variations);if(a)return {value:a.variation.value,variationKey:a.variationKey,reason:"TARGET_MATCH",matchedTargetName:r.name}}let o=R(i,e);return o?{value:o.variation.value,variationKey:o.variationKey,reason:i.defaultRollout?"DEFAULT_ROLLOUT":"DEFAULT_VARIATION"}:{value:void 0,variationKey:void 0,reason:"DEFAULT_VARIATION"}}var w="0.6.1",m=globalThis,u=m.document,g=m.navigator,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:w},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;if(!g?.sendBeacon){this.flush();return}let e=this.events.splice(0,this.options.maxBatchSize),t=this.buildPayload(e),n=new Blob([JSON.stringify(t)],{type:"application/json"});g.sendBeacon(`${this.options.baseUrl}/sdk/evaluations?key=${this.options.apiKey}`,n)||(this.events.unshift(...e),this.flush());}destroy(){this.timer&&(clearInterval(this.timer),this.timer=null),this.onVisibilityChange&&u?.removeEventListener&&u.removeEventListener("visibilitychange",this.onVisibilityChange),this.flush();}};var O="https://worker.gradual.so/api/v1";function V(){try{let i=globalThis,e=i.navigator;if(e&&e.product==="ReactNative")return "react-native";let t=i.window;if(t&&typeof t.document<"u")return "browser";if(i.process?.versions?.node)return "node";if(typeof globalThis<"u")return "edge"}catch{}return "unknown"}var D=V(),E=globalThis.process,I=typeof E?.hrtime?.bigint=="function";function h(){return I?E.hrtime.bigint():typeof performance<"u"?performance.now():Date.now()}function b(i){let e=h();return typeof i=="bigint"&&typeof e=="bigint"?Number((e-i)/1000n):Math.round((e-i)*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??O,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,n=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);}},n);});}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 n=await fetch(`${this.baseUrl}/sdk/snapshot?environment=${encodeURIComponent(this.environment)}`,{headers:{Authorization:`Bearer ${this.apiKey}`}});if(!n.ok){let o=await n.json().catch(()=>({}));throw new Error(`Gradual: Failed to fetch snapshot - ${o.error??n.statusText}`)}this.snapshot=await n.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:D},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={},n=new Set([...Object.keys(this.identifiedContext),...Object.keys(e?.context??{})]);for(let o of n)t[o]={...this.identifiedContext[o],...e?.context?.[o]};return t}evaluate(e,t){let n=this.ensureReady();if(!n.flags)return;let o=n.flags[e];if(!o){this.trackEvent({flagKey:e,variationKey:void 0,value:void 0,reason:"FLAG_NOT_FOUND",context:t,flagConfigVersion:n.version});return}let r=h(),a;try{a=d(o,t,n.segments??{});}catch(l){a={value:void 0,variationKey:void 0,reason:"ERROR",errorDetail:l instanceof Error?l.message:String(l)};}let s=b(r);return this.trackEvent({flagKey:e,variationKey:a.variationKey,value:a.value,reason:a.reason,context:t,matchedTargetName:a.matchedTargetName,flagConfigVersion:n.version,errorDetail:a.errorDetail,evaluationDurationUs:s}),a.value}trackEvent(e){if(!this.eventBuffer)return;let{context:t}=e,n=Object.keys(t),o={};for(let a of n)o[a]=Object.keys(t[a]??{});let r=n.length===0||n.every(a=>Object.keys(t[a]??{}).length===0);this.eventBuffer.push({flagKey:e.flagKey,variationKey:e.variationKey,value:e.value,reason:e.reason,contextKinds:n,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 n=this.evaluate(e,this.mergeContext(t));return typeof n=="boolean"?n:false}async get(e,t){await this.initPromise;let n=this.evaluate(e,this.mergeContext(t));return n??t.fallback}isEnabledSync(e,t){let n=this.evaluate(e,this.mergeContext(t));return typeof n=="boolean"?n:false}getSync(e,t){let n=this.evaluate(e,this.mergeContext(t));return n??t.fallback}evaluateSync(e,t){let n=this.ensureReady(),o=this.mergeContext(t);if(!n.flags)return {value:void 0,variationKey:void 0,reason:"FLAG_NOT_FOUND",flagConfigVersion:n.version};let r=n.flags[e];if(!r)return {value:void 0,variationKey:void 0,reason:"FLAG_NOT_FOUND",flagConfigVersion:n.version};let a=h(),s;try{s=d(r,o,n.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:b(a),flagConfigVersion:n.version}}trackSync(e,t,n){this.trackEvent({flagKey:e,variationKey:t.variationKey,value:t.value,reason:t.reason,context:this.mergeContext({context:n}),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 B(i){return new c(i)}
|
|
2
|
+
export{B as createGradual,d 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","doc","nav","EventBuffer","options","event","batch","payload","blob","DEFAULT_BASE_URL","detectPlatform","g","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","response","callback","createGradual"],"mappings":"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","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\nexport const SDK_VERSION = \"0.6.1\";\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;\nconst nav = g.navigator as\n | { sendBeacon?: (url: string, data: Blob) => boolean }\n | undefined;\n\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 using sendBeacon for reliable delivery during page unload.\n * Falls back to regular flush if sendBeacon is unavailable.\n */\n private flushBeacon(): void {\n if (this.events.length === 0) {\n return;\n }\n\n if (!nav?.sendBeacon) {\n this.flush();\n return;\n }\n\n const batch = this.events.splice(0, this.options.maxBatchSize);\n const payload = this.buildPayload(batch);\n const blob = new Blob([JSON.stringify(payload)], {\n type: \"application/json\",\n });\n\n const sent = nav.sendBeacon(\n `${this.options.baseUrl}/sdk/evaluations?key=${this.options.apiKey}`,\n blob\n );\n\n if (!sent) {\n // sendBeacon failed (e.g. payload too large), put events back\n this.events.unshift(...batch);\n this.flush();\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 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\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 };\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 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","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","nav","EventBuffer","options","event","batch","payload","blob","DEFAULT_BASE_URL","detectPlatform","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":"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","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\nexport const SDK_VERSION = \"0.6.1\";\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;\nconst nav = g.navigator as\n | { sendBeacon?: (url: string, data: Blob) => boolean }\n | undefined;\n\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 using sendBeacon for reliable delivery during page unload.\n * Falls back to regular flush if sendBeacon is unavailable.\n */\n private flushBeacon(): void {\n if (this.events.length === 0) {\n return;\n }\n\n if (!nav?.sendBeacon) {\n this.flush();\n return;\n }\n\n const batch = this.events.splice(0, this.options.maxBatchSize);\n const payload = this.buildPayload(batch);\n const blob = new Blob([JSON.stringify(payload)], {\n type: \"application/json\",\n });\n\n const sent = nav.sendBeacon(\n `${this.options.baseUrl}/sdk/evaluations?key=${this.options.apiKey}`,\n blob\n );\n\n if (!sent) {\n // sendBeacon failed (e.g. payload too large), put events back\n this.events.unshift(...batch);\n this.flush();\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"]}
|