@schematichq/schematic-js 1.0.0 → 1.0.2

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.
@@ -1,3 +1,3 @@
1
- "use strict";(()=>{var X=Object.create;var R=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var Y=Object.getOwnPropertyNames;var Z=Object.getPrototypeOf,ee=Object.prototype.hasOwnProperty;var te=(s,t)=>()=>(t||s((t={exports:{}}).exports,t),t.exports);var re=(s,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Y(t))!ee.call(s,o)&&o!==n&&R(s,o,{get:()=>t[o],enumerable:!(i=z(t,o))||i.enumerable});return s};var ne=(s,t,n)=>(n=s!=null?X(Z(s)):{},re(t||!s||!s.__esModule?R(n,"default",{value:s,enumerable:!0}):n,s));var V=te(j=>{(function(s){var t=function(n){var i=typeof globalThis<"u"&&globalThis||typeof s<"u"&&s||typeof i<"u"&&i,o={searchParams:"URLSearchParams"in i,iterable:"Symbol"in i&&"iterator"in Symbol,blob:"FileReader"in i&&"Blob"in i&&function(){try{return new Blob,!0}catch{return!1}}(),formData:"FormData"in i,arrayBuffer:"ArrayBuffer"in i};function y(e){return e&&DataView.prototype.isPrototypeOf(e)}if(o.arrayBuffer)var h=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],E=ArrayBuffer.isView||function(e){return e&&h.indexOf(Object.prototype.toString.call(e))>-1};function b(e){if(typeof e!="string"&&(e=String(e)),/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(e)||e==="")throw new TypeError('Invalid character in header field name: "'+e+'"');return e.toLowerCase()}function S(e){return typeof e!="string"&&(e=String(e)),e}function w(e){var r={next:function(){var a=e.shift();return{done:a===void 0,value:a}}};return o.iterable&&(r[Symbol.iterator]=function(){return r}),r}function d(e){this.map={},e instanceof d?e.forEach(function(r,a){this.append(a,r)},this):Array.isArray(e)?e.forEach(function(r){this.append(r[0],r[1])},this):e&&Object.getOwnPropertyNames(e).forEach(function(r){this.append(r,e[r])},this)}d.prototype.append=function(e,r){e=b(e),r=S(r);var a=this.map[e];this.map[e]=a?a+", "+r:r},d.prototype.delete=function(e){delete this.map[b(e)]},d.prototype.get=function(e){return e=b(e),this.has(e)?this.map[e]:null},d.prototype.has=function(e){return this.map.hasOwnProperty(b(e))},d.prototype.set=function(e,r){this.map[b(e)]=S(r)},d.prototype.forEach=function(e,r){for(var a in this.map)this.map.hasOwnProperty(a)&&e.call(r,this.map[a],a,this)},d.prototype.keys=function(){var e=[];return this.forEach(function(r,a){e.push(a)}),w(e)},d.prototype.values=function(){var e=[];return this.forEach(function(r){e.push(r)}),w(e)},d.prototype.entries=function(){var e=[];return this.forEach(function(r,a){e.push([a,r])}),w(e)},o.iterable&&(d.prototype[Symbol.iterator]=d.prototype.entries);function O(e){if(e.bodyUsed)return Promise.reject(new TypeError("Already read"));e.bodyUsed=!0}function D(e){return new Promise(function(r,a){e.onload=function(){r(e.result)},e.onerror=function(){a(e.error)}})}function M(e){var r=new FileReader,a=D(r);return r.readAsArrayBuffer(e),a}function q(e){var r=new FileReader,a=D(r);return r.readAsText(e),a}function H(e){for(var r=new Uint8Array(e),a=new Array(r.length),u=0;u<r.length;u++)a[u]=String.fromCharCode(r[u]);return a.join("")}function C(e){if(e.slice)return e.slice(0);var r=new Uint8Array(e.byteLength);return r.set(new Uint8Array(e)),r.buffer}function L(){return this.bodyUsed=!1,this._initBody=function(e){this.bodyUsed=this.bodyUsed,this._bodyInit=e,e?typeof e=="string"?this._bodyText=e:o.blob&&Blob.prototype.isPrototypeOf(e)?this._bodyBlob=e:o.formData&&FormData.prototype.isPrototypeOf(e)?this._bodyFormData=e:o.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)?this._bodyText=e.toString():o.arrayBuffer&&o.blob&&y(e)?(this._bodyArrayBuffer=C(e.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer])):o.arrayBuffer&&(ArrayBuffer.prototype.isPrototypeOf(e)||E(e))?this._bodyArrayBuffer=C(e):this._bodyText=e=Object.prototype.toString.call(e):this._bodyText="",this.headers.get("content-type")||(typeof e=="string"?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type?this.headers.set("content-type",this._bodyBlob.type):o.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)&&this.headers.set("content-type","application/x-www-form-urlencoded;charset=UTF-8"))},o.blob&&(this.blob=function(){var e=O(this);if(e)return e;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){if(this._bodyArrayBuffer){var e=O(this);return e||(ArrayBuffer.isView(this._bodyArrayBuffer)?Promise.resolve(this._bodyArrayBuffer.buffer.slice(this._bodyArrayBuffer.byteOffset,this._bodyArrayBuffer.byteOffset+this._bodyArrayBuffer.byteLength)):Promise.resolve(this._bodyArrayBuffer))}else return this.blob().then(M)}),this.text=function(){var e=O(this);if(e)return e;if(this._bodyBlob)return q(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(H(this._bodyArrayBuffer));if(this._bodyFormData)throw new Error("could not read FormData body as text");return Promise.resolve(this._bodyText)},o.formData&&(this.formData=function(){return this.text().then(J)}),this.json=function(){return this.text().then(JSON.parse)},this}var W=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];function K(e){var r=e.toUpperCase();return W.indexOf(r)>-1?r:e}function v(e,r){if(!(this instanceof v))throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');r=r||{};var a=r.body;if(e instanceof v){if(e.bodyUsed)throw new TypeError("Already read");this.url=e.url,this.credentials=e.credentials,r.headers||(this.headers=new d(e.headers)),this.method=e.method,this.mode=e.mode,this.signal=e.signal,!a&&e._bodyInit!=null&&(a=e._bodyInit,e.bodyUsed=!0)}else this.url=String(e);if(this.credentials=r.credentials||this.credentials||"same-origin",(r.headers||!this.headers)&&(this.headers=new d(r.headers)),this.method=K(r.method||this.method||"GET"),this.mode=r.mode||this.mode||null,this.signal=r.signal||this.signal,this.referrer=null,(this.method==="GET"||this.method==="HEAD")&&a)throw new TypeError("Body not allowed for GET or HEAD requests");if(this._initBody(a),(this.method==="GET"||this.method==="HEAD")&&(r.cache==="no-store"||r.cache==="no-cache")){var u=/([?&])_=[^&]*/;if(u.test(this.url))this.url=this.url.replace(u,"$1_="+new Date().getTime());else{var f=/\?/;this.url+=(f.test(this.url)?"&":"?")+"_="+new Date().getTime()}}}v.prototype.clone=function(){return new v(this,{body:this._bodyInit})};function J(e){var r=new FormData;return e.trim().split("&").forEach(function(a){if(a){var u=a.split("="),f=u.shift().replace(/\+/g," "),c=u.join("=").replace(/\+/g," ");r.append(decodeURIComponent(f),decodeURIComponent(c))}}),r}function Q(e){var r=new d,a=e.replace(/\r?\n[\t ]+/g," ");return a.split("\r").map(function(u){return u.indexOf(`
2
- `)===0?u.substr(1,u.length):u}).forEach(function(u){var f=u.split(":"),c=f.shift().trim();if(c){var T=f.join(":").trim();r.append(c,T)}}),r}L.call(v.prototype);function m(e,r){if(!(this instanceof m))throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');r||(r={}),this.type="default",this.status=r.status===void 0?200:r.status,this.ok=this.status>=200&&this.status<300,this.statusText=r.statusText===void 0?"":""+r.statusText,this.headers=new d(r.headers),this.url=r.url||"",this._initBody(e)}L.call(m.prototype),m.prototype.clone=function(){return new m(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new d(this.headers),url:this.url})},m.error=function(){var e=new m(null,{status:0,statusText:""});return e.type="error",e};var $=[301,302,303,307,308];m.redirect=function(e,r){if($.indexOf(r)===-1)throw new RangeError("Invalid status code");return new m(null,{status:r,headers:{location:e}})},n.DOMException=i.DOMException;try{new n.DOMException}catch{n.DOMException=function(r,a){this.message=r,this.name=a;var u=Error(r);this.stack=u.stack},n.DOMException.prototype=Object.create(Error.prototype),n.DOMException.prototype.constructor=n.DOMException}function k(e,r){return new Promise(function(a,u){var f=new v(e,r);if(f.signal&&f.signal.aborted)return u(new n.DOMException("Aborted","AbortError"));var c=new XMLHttpRequest;function T(){c.abort()}c.onload=function(){var p={status:c.status,statusText:c.statusText,headers:Q(c.getAllResponseHeaders()||"")};p.url="responseURL"in c?c.responseURL:p.headers.get("X-Request-URL");var P="response"in c?c.response:c.responseText;setTimeout(function(){a(new m(P,p))},0)},c.onerror=function(){setTimeout(function(){u(new TypeError("Network request failed"))},0)},c.ontimeout=function(){setTimeout(function(){u(new TypeError("Network request failed"))},0)},c.onabort=function(){setTimeout(function(){u(new n.DOMException("Aborted","AbortError"))},0)};function G(p){try{return p===""&&i.location.href?i.location.href:p}catch{return p}}c.open(f.method,G(f.url),!0),f.credentials==="include"?c.withCredentials=!0:f.credentials==="omit"&&(c.withCredentials=!1),"responseType"in c&&(o.blob?c.responseType="blob":o.arrayBuffer&&f.headers.get("Content-Type")&&f.headers.get("Content-Type").indexOf("application/octet-stream")!==-1&&(c.responseType="arraybuffer")),r&&typeof r.headers=="object"&&!(r.headers instanceof d)?Object.getOwnPropertyNames(r.headers).forEach(function(p){c.setRequestHeader(p,S(r.headers[p]))}):f.headers.forEach(function(p,P){c.setRequestHeader(P,p)}),f.signal&&(f.signal.addEventListener("abort",T),c.onreadystatechange=function(){c.readyState===4&&f.signal.removeEventListener("abort",T)}),c.send(typeof f._bodyInit>"u"?null:f._bodyInit)})}return k.polyfill=!0,i.fetch||(i.fetch=k,i.Headers=d,i.Request=v,i.Response=m),n.Headers=d,n.Request=v,n.Response=m,n.fetch=k,n}({})})(typeof self<"u"?self:j)});var l=[];for(U=0;U<256;++U)l.push((U+256).toString(16).slice(1));var U;function F(s,t=0){return(l[s[t+0]]+l[s[t+1]]+l[s[t+2]]+l[s[t+3]]+"-"+l[s[t+4]]+l[s[t+5]]+"-"+l[s[t+6]]+l[s[t+7]]+"-"+l[s[t+8]]+l[s[t+9]]+"-"+l[s[t+10]]+l[s[t+11]]+l[s[t+12]]+l[s[t+13]]+l[s[t+14]]+l[s[t+15]]).toLowerCase()}var A,ie=new Uint8Array(16);function _(){if(!A&&(A=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!A))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return A(ie)}var oe=typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto),I={randomUUID:oe};function se(s,t,n){if(I.randomUUID&&!t&&!s)return I.randomUUID();s=s||{};var i=s.random||(s.rng||_)();if(i[6]=i[6]&15|64,i[8]=i[8]&63|128,t){n=n||0;for(var o=0;o<16;++o)t[n+o]=i[o];return t}return F(i)}var x=se;var be=ne(V());function g(s){let t=Object.keys(s).reduce((n,i)=>{let y=Object.keys(s[i]||{}).sort().reduce((h,E)=>(h[E]=s[i][E],h),{});return n[i]=y,n},{});return JSON.stringify(t)}var N="schematicId";var B=class{apiKey;apiUrl="https://api.schematichq.com";conn=null;context={};eventQueue;eventUrl="https://c.schematichq.com";flagListener;flagValueListeners={};isPending=!0;isPendingListeners=new Set;storage;useWebSocket=!1;values={};webSocketUrl="wss://api.schematichq.com";constructor(t,n){this.apiKey=t,this.eventQueue=[],this.useWebSocket=n?.useWebSocket??!1,this.flagListener=n?.flagListener,n?.storage?this.storage=n.storage:typeof localStorage<"u"&&(this.storage=localStorage),n?.apiUrl!==void 0&&(this.apiUrl=n.apiUrl),n?.eventUrl!==void 0&&(this.eventUrl=n.eventUrl),n?.webSocketUrl!==void 0&&(this.webSocketUrl=n.webSocketUrl),typeof window<"u"&&window?.addEventListener&&window.addEventListener("beforeunload",()=>{this.flushEventQueue()})}async checkFlag(t){let{fallback:n=!1,key:i}=t,o=t.context||this.context;if(this.useWebSocket){let h=this.values[g(o)]??{};return typeof h[i]>"u"?n:h[i]}let y=`${this.apiUrl}/flags/${i}/check`;return fetch(y,{method:"POST",headers:{"X-Schematic-Api-Key":this.apiKey,"Content-Type":"application/json;charset=UTF-8"},body:JSON.stringify(o)}).then(h=>{if(!h.ok)throw new Error("Network response was not ok");return h.json()}).then(h=>h.data.value).catch(h=>(console.error("There was a problem with the fetch operation:",h),n))}checkFlags=async t=>{t=t||this.context;let n=`${this.apiUrl}/flags/check`,i=JSON.stringify(t);return fetch(n,{method:"POST",headers:{"Content-Type":"application/json;charset=UTF-8","X-Schematic-Api-Key":this.apiKey},body:i}).then(o=>{if(!o.ok)throw new Error("Network response was not ok");return o.json()}).then(o=>(o?.data?.flags??[]).reduce((y,h)=>(y[h.flag]=h.value,y),{})).catch(o=>(console.error("There was a problem with the fetch operation:",o),!1))};identify=t=>(this.setContext({company:t.company?.keys,user:t.keys}),this.handleEvent("identify",t));setContext=async t=>{if(!this.useWebSocket)return this.context=t,Promise.resolve();try{this.setIsPending(!0),this.conn||(this.conn=this.wsConnect());let n=await this.conn;await this.wsSendMessage(n,t)}catch(n){console.error("Error setting Schematic context:",n)}};track=t=>{let{company:n,user:i,event:o,traits:y}=t;return this.handleEvent("track",{company:n??this.context.company,event:o,traits:y??{},user:i??this.context.user})};flushEventQueue=()=>{for(;this.eventQueue.length>0;){let t=this.eventQueue.shift();t&&this.sendEvent(t)}};getAnonymousId=()=>{if(!this.storage)return x();let t=this.storage.getItem(N);if(typeof t<"u")return t;let n=x();return this.storage.setItem(N,n),n};handleEvent=(t,n)=>{let i={api_key:this.apiKey,body:n,sent_at:new Date().toISOString(),tracker_event_id:x(),tracker_user_id:this.getAnonymousId(),type:t};return document?.hidden?this.storeEvent(i):this.sendEvent(i)};sendEvent=async t=>{let n=`${this.eventUrl}/e`,i=JSON.stringify(t);try{await fetch(n,{method:"POST",headers:{"Content-Type":"application/json;charset=UTF-8"},body:i})}catch(o){console.error("Error sending Schematic event: ",o)}return Promise.resolve()};storeEvent=t=>(this.eventQueue.push(t),Promise.resolve());cleanup=async()=>{if(this.conn)try{(await this.conn).close()}catch(t){console.error("Error during cleanup:",t)}finally{this.conn=null}};wsConnect=()=>new Promise((t,n)=>{let i=`${this.webSocketUrl}/flags/bootstrap`,o=new WebSocket(i);o.onopen=()=>{t(o)},o.onerror=y=>{n(y)},o.onclose=()=>{this.conn=null}});wsSendMessage=(t,n)=>new Promise((i,o)=>{if(g(n)==g(this.context)){i();return}this.context=n;let y=()=>{let h=!1,E=b=>{let S=JSON.parse(b.data);g(n)in this.values||(this.values[g(n)]={}),(S.flags??[]).forEach(w=>{this.values[g(n)][w.flag]=w.value,this.notifyFlagValueListeners(w.flag)}),this.flagListener&&this.flagListener(this.getFlagValues()),this.setIsPending(!1),h||(h=!0,i())};t.addEventListener("message",E),t.send(JSON.stringify({apiKey:this.apiKey,data:n}))};t.readyState===WebSocket.OPEN?y():t.readyState===WebSocket.CONNECTING?t.addEventListener("open",y):o("WebSocket is not open or connecting")});getIsPending=()=>this.isPending;addIsPendingListener=t=>(this.isPendingListeners.add(t),()=>{this.isPendingListeners.delete(t)});setIsPending=t=>{this.isPending=t,this.isPendingListeners.forEach(n=>n())};getFlagValue=t=>this.getFlagValues()[t];getFlagValues=()=>{let t=g(this.context);return this.values[t]??{}};addFlagValueListener=(t,n)=>(t in this.flagValueListeners||(this.flagValueListeners[t]=new Set),this.flagValueListeners[t].add(n),()=>{this.flagValueListeners[t].delete(n)});notifyFlagValueListeners=t=>{(this.flagValueListeners?.[t]??[]).forEach(i=>i())}};window.Schematic=B;})();
1
+ "use strict";(()=>{var z=Object.create;var R=Object.defineProperty;var Y=Object.getOwnPropertyDescriptor;var Z=Object.getOwnPropertyNames;var ee=Object.getPrototypeOf,te=Object.prototype.hasOwnProperty;var re=(o,t)=>()=>(t||o((t={exports:{}}).exports,t),t.exports);var ne=(o,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Z(t))!te.call(o,s)&&s!==n&&R(o,s,{get:()=>t[s],enumerable:!(i=Y(t,s))||i.enumerable});return o};var ie=(o,t,n)=>(n=o!=null?z(ee(o)):{},ne(t||!o||!o.__esModule?R(n,"default",{value:o,enumerable:!0}):n,o));var V=re(j=>{(function(o){var t=function(n){var i=typeof globalThis<"u"&&globalThis||typeof o<"u"&&o||typeof i<"u"&&i,s={searchParams:"URLSearchParams"in i,iterable:"Symbol"in i&&"iterator"in Symbol,blob:"FileReader"in i&&"Blob"in i&&function(){try{return new Blob,!0}catch{return!1}}(),formData:"FormData"in i,arrayBuffer:"ArrayBuffer"in i};function y(e){return e&&DataView.prototype.isPrototypeOf(e)}if(s.arrayBuffer)var h=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],E=ArrayBuffer.isView||function(e){return e&&h.indexOf(Object.prototype.toString.call(e))>-1};function w(e){if(typeof e!="string"&&(e=String(e)),/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(e)||e==="")throw new TypeError('Invalid character in header field name: "'+e+'"');return e.toLowerCase()}function S(e){return typeof e!="string"&&(e=String(e)),e}function v(e){var r={next:function(){var a=e.shift();return{done:a===void 0,value:a}}};return s.iterable&&(r[Symbol.iterator]=function(){return r}),r}function d(e){this.map={},e instanceof d?e.forEach(function(r,a){this.append(a,r)},this):Array.isArray(e)?e.forEach(function(r){this.append(r[0],r[1])},this):e&&Object.getOwnPropertyNames(e).forEach(function(r){this.append(r,e[r])},this)}d.prototype.append=function(e,r){e=w(e),r=S(r);var a=this.map[e];this.map[e]=a?a+", "+r:r},d.prototype.delete=function(e){delete this.map[w(e)]},d.prototype.get=function(e){return e=w(e),this.has(e)?this.map[e]:null},d.prototype.has=function(e){return this.map.hasOwnProperty(w(e))},d.prototype.set=function(e,r){this.map[w(e)]=S(r)},d.prototype.forEach=function(e,r){for(var a in this.map)this.map.hasOwnProperty(a)&&e.call(r,this.map[a],a,this)},d.prototype.keys=function(){var e=[];return this.forEach(function(r,a){e.push(a)}),v(e)},d.prototype.values=function(){var e=[];return this.forEach(function(r){e.push(r)}),v(e)},d.prototype.entries=function(){var e=[];return this.forEach(function(r,a){e.push([a,r])}),v(e)},s.iterable&&(d.prototype[Symbol.iterator]=d.prototype.entries);function O(e){if(e.bodyUsed)return Promise.reject(new TypeError("Already read"));e.bodyUsed=!0}function F(e){return new Promise(function(r,a){e.onload=function(){r(e.result)},e.onerror=function(){a(e.error)}})}function M(e){var r=new FileReader,a=F(r);return r.readAsArrayBuffer(e),a}function q(e){var r=new FileReader,a=F(r);return r.readAsText(e),a}function W(e){for(var r=new Uint8Array(e),a=new Array(r.length),u=0;u<r.length;u++)a[u]=String.fromCharCode(r[u]);return a.join("")}function I(e){if(e.slice)return e.slice(0);var r=new Uint8Array(e.byteLength);return r.set(new Uint8Array(e)),r.buffer}function D(){return this.bodyUsed=!1,this._initBody=function(e){this.bodyUsed=this.bodyUsed,this._bodyInit=e,e?typeof e=="string"?this._bodyText=e:s.blob&&Blob.prototype.isPrototypeOf(e)?this._bodyBlob=e:s.formData&&FormData.prototype.isPrototypeOf(e)?this._bodyFormData=e:s.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)?this._bodyText=e.toString():s.arrayBuffer&&s.blob&&y(e)?(this._bodyArrayBuffer=I(e.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer])):s.arrayBuffer&&(ArrayBuffer.prototype.isPrototypeOf(e)||E(e))?this._bodyArrayBuffer=I(e):this._bodyText=e=Object.prototype.toString.call(e):this._bodyText="",this.headers.get("content-type")||(typeof e=="string"?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type?this.headers.set("content-type",this._bodyBlob.type):s.searchParams&&URLSearchParams.prototype.isPrototypeOf(e)&&this.headers.set("content-type","application/x-www-form-urlencoded;charset=UTF-8"))},s.blob&&(this.blob=function(){var e=O(this);if(e)return e;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){if(this._bodyArrayBuffer){var e=O(this);return e||(ArrayBuffer.isView(this._bodyArrayBuffer)?Promise.resolve(this._bodyArrayBuffer.buffer.slice(this._bodyArrayBuffer.byteOffset,this._bodyArrayBuffer.byteOffset+this._bodyArrayBuffer.byteLength)):Promise.resolve(this._bodyArrayBuffer))}else return this.blob().then(M)}),this.text=function(){var e=O(this);if(e)return e;if(this._bodyBlob)return q(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(W(this._bodyArrayBuffer));if(this._bodyFormData)throw new Error("could not read FormData body as text");return Promise.resolve(this._bodyText)},s.formData&&(this.formData=function(){return this.text().then(Q)}),this.json=function(){return this.text().then(JSON.parse)},this}var K=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];function J(e){var r=e.toUpperCase();return K.indexOf(r)>-1?r:e}function g(e,r){if(!(this instanceof g))throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');r=r||{};var a=r.body;if(e instanceof g){if(e.bodyUsed)throw new TypeError("Already read");this.url=e.url,this.credentials=e.credentials,r.headers||(this.headers=new d(e.headers)),this.method=e.method,this.mode=e.mode,this.signal=e.signal,!a&&e._bodyInit!=null&&(a=e._bodyInit,e.bodyUsed=!0)}else this.url=String(e);if(this.credentials=r.credentials||this.credentials||"same-origin",(r.headers||!this.headers)&&(this.headers=new d(r.headers)),this.method=J(r.method||this.method||"GET"),this.mode=r.mode||this.mode||null,this.signal=r.signal||this.signal,this.referrer=null,(this.method==="GET"||this.method==="HEAD")&&a)throw new TypeError("Body not allowed for GET or HEAD requests");if(this._initBody(a),(this.method==="GET"||this.method==="HEAD")&&(r.cache==="no-store"||r.cache==="no-cache")){var u=/([?&])_=[^&]*/;if(u.test(this.url))this.url=this.url.replace(u,"$1_="+new Date().getTime());else{var f=/\?/;this.url+=(f.test(this.url)?"&":"?")+"_="+new Date().getTime()}}}g.prototype.clone=function(){return new g(this,{body:this._bodyInit})};function Q(e){var r=new FormData;return e.trim().split("&").forEach(function(a){if(a){var u=a.split("="),f=u.shift().replace(/\+/g," "),c=u.join("=").replace(/\+/g," ");r.append(decodeURIComponent(f),decodeURIComponent(c))}}),r}function $(e){var r=new d,a=e.replace(/\r?\n[\t ]+/g," ");return a.split("\r").map(function(u){return u.indexOf(`
2
+ `)===0?u.substr(1,u.length):u}).forEach(function(u){var f=u.split(":"),c=f.shift().trim();if(c){var T=f.join(":").trim();r.append(c,T)}}),r}D.call(g.prototype);function m(e,r){if(!(this instanceof m))throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');r||(r={}),this.type="default",this.status=r.status===void 0?200:r.status,this.ok=this.status>=200&&this.status<300,this.statusText=r.statusText===void 0?"":""+r.statusText,this.headers=new d(r.headers),this.url=r.url||"",this._initBody(e)}D.call(m.prototype),m.prototype.clone=function(){return new m(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new d(this.headers),url:this.url})},m.error=function(){var e=new m(null,{status:0,statusText:""});return e.type="error",e};var G=[301,302,303,307,308];m.redirect=function(e,r){if(G.indexOf(r)===-1)throw new RangeError("Invalid status code");return new m(null,{status:r,headers:{location:e}})},n.DOMException=i.DOMException;try{new n.DOMException}catch{n.DOMException=function(r,a){this.message=r,this.name=a;var u=Error(r);this.stack=u.stack},n.DOMException.prototype=Object.create(Error.prototype),n.DOMException.prototype.constructor=n.DOMException}function k(e,r){return new Promise(function(a,u){var f=new g(e,r);if(f.signal&&f.signal.aborted)return u(new n.DOMException("Aborted","AbortError"));var c=new XMLHttpRequest;function T(){c.abort()}c.onload=function(){var p={status:c.status,statusText:c.statusText,headers:$(c.getAllResponseHeaders()||"")};p.url="responseURL"in c?c.responseURL:p.headers.get("X-Request-URL");var P="response"in c?c.response:c.responseText;setTimeout(function(){a(new m(P,p))},0)},c.onerror=function(){setTimeout(function(){u(new TypeError("Network request failed"))},0)},c.ontimeout=function(){setTimeout(function(){u(new TypeError("Network request failed"))},0)},c.onabort=function(){setTimeout(function(){u(new n.DOMException("Aborted","AbortError"))},0)};function X(p){try{return p===""&&i.location.href?i.location.href:p}catch{return p}}c.open(f.method,X(f.url),!0),f.credentials==="include"?c.withCredentials=!0:f.credentials==="omit"&&(c.withCredentials=!1),"responseType"in c&&(s.blob?c.responseType="blob":s.arrayBuffer&&f.headers.get("Content-Type")&&f.headers.get("Content-Type").indexOf("application/octet-stream")!==-1&&(c.responseType="arraybuffer")),r&&typeof r.headers=="object"&&!(r.headers instanceof d)?Object.getOwnPropertyNames(r.headers).forEach(function(p){c.setRequestHeader(p,S(r.headers[p]))}):f.headers.forEach(function(p,P){c.setRequestHeader(P,p)}),f.signal&&(f.signal.addEventListener("abort",T),c.onreadystatechange=function(){c.readyState===4&&f.signal.removeEventListener("abort",T)}),c.send(typeof f._bodyInit>"u"?null:f._bodyInit)})}return k.polyfill=!0,i.fetch||(i.fetch=k,i.Headers=d,i.Request=g,i.Response=m),n.Headers=d,n.Request=g,n.Response=m,n.fetch=k,n}({})})(typeof self<"u"?self:j)});var l=[];for(U=0;U<256;++U)l.push((U+256).toString(16).slice(1));var U;function C(o,t=0){return(l[o[t+0]]+l[o[t+1]]+l[o[t+2]]+l[o[t+3]]+"-"+l[o[t+4]]+l[o[t+5]]+"-"+l[o[t+6]]+l[o[t+7]]+"-"+l[o[t+8]]+l[o[t+9]]+"-"+l[o[t+10]]+l[o[t+11]]+l[o[t+12]]+l[o[t+13]]+l[o[t+14]]+l[o[t+15]]).toLowerCase()}var A,se=new Uint8Array(16);function _(){if(!A&&(A=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!A))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return A(se)}var oe=typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto),L={randomUUID:oe};function ae(o,t,n){if(L.randomUUID&&!t&&!o)return L.randomUUID();o=o||{};var i=o.random||(o.rng||_)();if(i[6]=i[6]&15|64,i[8]=i[8]&63|128,t){n=n||0;for(var s=0;s<16;++s)t[n+s]=i[s];return t}return C(i)}var x=ae;var we=ie(V());function b(o){let t=Object.keys(o).reduce((n,i)=>{let y=Object.keys(o[i]||{}).sort().reduce((h,E)=>(h[E]=o[i][E],h),{});return n[i]=y,n},{});return JSON.stringify(t)}var H="schematicId";var B=class{additionalHeaders={};apiKey;apiUrl="https://api.schematichq.com";conn=null;context={};eventQueue;eventUrl="https://c.schematichq.com";flagListener;flagValueListeners={};isPending=!0;isPendingListeners=new Set;storage;useWebSocket=!1;values={};webSocketUrl="wss://api.schematichq.com";constructor(t,n){this.apiKey=t,this.eventQueue=[],this.useWebSocket=n?.useWebSocket??!1,this.flagListener=n?.flagListener,n?.additionalHeaders&&(this.additionalHeaders=n.additionalHeaders),n?.storage?this.storage=n.storage:typeof localStorage<"u"&&(this.storage=localStorage),n?.apiUrl!==void 0&&(this.apiUrl=n.apiUrl),n?.eventUrl!==void 0&&(this.eventUrl=n.eventUrl),n?.webSocketUrl!==void 0&&(this.webSocketUrl=n.webSocketUrl),typeof window<"u"&&window?.addEventListener&&window.addEventListener("beforeunload",()=>{this.flushEventQueue()})}async checkFlag(t){let{fallback:n=!1,key:i}=t,s=t.context||this.context;if(this.useWebSocket){let h=this.values[b(s)]??{};return typeof h[i]>"u"?n:h[i]}let y=`${this.apiUrl}/flags/${i}/check`;return fetch(y,{method:"POST",headers:{...this.additionalHeaders??{},"Content-Type":"application/json;charset=UTF-8","X-Schematic-Api-Key":this.apiKey},body:JSON.stringify(s)}).then(h=>{if(!h.ok)throw new Error("Network response was not ok");return h.json()}).then(h=>h.data.value).catch(h=>(console.error("There was a problem with the fetch operation:",h),n))}checkFlags=async t=>{t=t||this.context;let n=`${this.apiUrl}/flags/check`,i=JSON.stringify(t);return fetch(n,{method:"POST",headers:{...this.additionalHeaders??{},"Content-Type":"application/json;charset=UTF-8","X-Schematic-Api-Key":this.apiKey},body:i}).then(s=>{if(!s.ok)throw new Error("Network response was not ok");return s.json()}).then(s=>(s?.data?.flags??[]).reduce((y,h)=>(y[h.flag]=h.value,y),{})).catch(s=>(console.error("There was a problem with the fetch operation:",s),!1))};identify=t=>(this.setContext({company:t.company?.keys,user:t.keys}),this.handleEvent("identify",t));setContext=async t=>{if(!this.useWebSocket)return this.context=t,Promise.resolve();try{this.setIsPending(!0),this.conn||(this.conn=this.wsConnect());let n=await this.conn;await this.wsSendMessage(n,t)}catch(n){console.error("Error setting Schematic context:",n)}};track=t=>{let{company:n,user:i,event:s,traits:y}=t;return this.handleEvent("track",{company:n??this.context.company,event:s,traits:y??{},user:i??this.context.user})};flushEventQueue=()=>{for(;this.eventQueue.length>0;){let t=this.eventQueue.shift();t&&this.sendEvent(t)}};getAnonymousId=()=>{if(!this.storage)return x();let t=this.storage.getItem(H);if(typeof t<"u")return t;let n=x();return this.storage.setItem(H,n),n};handleEvent=(t,n)=>{let i={api_key:this.apiKey,body:n,sent_at:new Date().toISOString(),tracker_event_id:x(),tracker_user_id:this.getAnonymousId(),type:t};return document?.hidden?this.storeEvent(i):this.sendEvent(i)};sendEvent=async t=>{let n=`${this.eventUrl}/e`,i=JSON.stringify(t);try{await fetch(n,{method:"POST",headers:{...this.additionalHeaders??{},"Content-Type":"application/json;charset=UTF-8"},body:i})}catch(s){console.error("Error sending Schematic event: ",s)}return Promise.resolve()};storeEvent=t=>(this.eventQueue.push(t),Promise.resolve());cleanup=async()=>{if(this.conn)try{(await this.conn).close()}catch(t){console.error("Error during cleanup:",t)}finally{this.conn=null}};wsConnect=()=>new Promise((t,n)=>{let i=`${this.webSocketUrl}/flags/bootstrap`,s=new WebSocket(i);s.onopen=()=>{t(s)},s.onerror=y=>{n(y)},s.onclose=()=>{this.conn=null}});wsSendMessage=(t,n)=>new Promise((i,s)=>{if(b(n)==b(this.context))return i(this.setIsPending(!1));this.context=n;let y=()=>{let h=!1,E=w=>{let S=JSON.parse(w.data);b(n)in this.values||(this.values[b(n)]={}),(S.flags??[]).forEach(v=>{this.values[b(n)][v.flag]=v.value,this.notifyFlagValueListeners(v.flag,v.value)}),this.flagListener&&this.flagListener(this.getFlagValues()),this.setIsPending(!1),h||(h=!0,i())};t.addEventListener("message",E),t.send(JSON.stringify({apiKey:this.apiKey,data:n}))};t.readyState===WebSocket.OPEN?y():t.readyState===WebSocket.CONNECTING?t.addEventListener("open",y):s("WebSocket is not open or connecting")});getIsPending=()=>this.isPending;addIsPendingListener=t=>(this.isPendingListeners.add(t),()=>{this.isPendingListeners.delete(t)});setIsPending=t=>{this.isPending=t,this.isPendingListeners.forEach(n=>N(n,t))};getFlagValue=t=>this.getFlagValues()[t];getFlagValues=()=>{let t=b(this.context);return this.values[t]??{}};addFlagValueListener=(t,n)=>(t in this.flagValueListeners||(this.flagValueListeners[t]=new Set),this.flagValueListeners[t].add(n),()=>{this.flagValueListeners[t].delete(n)});notifyFlagValueListeners=(t,n)=>{(this.flagValueListeners?.[t]??[]).forEach(s=>N(s,n))}},N=(o,t)=>{o.length>0?o(t):o()};window.Schematic=B;})();
3
3
  /* @preserve */
@@ -610,6 +610,7 @@ function contextString(context) {
610
610
  // src/index.ts
611
611
  var anonymousIdKey = "schematicId";
612
612
  var Schematic = class {
613
+ additionalHeaders = {};
613
614
  apiKey;
614
615
  apiUrl = "https://api.schematichq.com";
615
616
  conn = null;
@@ -629,6 +630,9 @@ var Schematic = class {
629
630
  this.eventQueue = [];
630
631
  this.useWebSocket = options?.useWebSocket ?? false;
631
632
  this.flagListener = options?.flagListener;
633
+ if (options?.additionalHeaders) {
634
+ this.additionalHeaders = options.additionalHeaders;
635
+ }
632
636
  if (options?.storage) {
633
637
  this.storage = options.storage;
634
638
  } else if (typeof localStorage !== "undefined") {
@@ -662,8 +666,9 @@ var Schematic = class {
662
666
  return fetch(requestUrl, {
663
667
  method: "POST",
664
668
  headers: {
665
- "X-Schematic-Api-Key": this.apiKey,
666
- "Content-Type": "application/json;charset=UTF-8"
669
+ ...this.additionalHeaders ?? {},
670
+ "Content-Type": "application/json;charset=UTF-8",
671
+ "X-Schematic-Api-Key": this.apiKey
667
672
  },
668
673
  body: JSON.stringify(context)
669
674
  }).then((response) => {
@@ -686,6 +691,7 @@ var Schematic = class {
686
691
  return fetch(requestUrl, {
687
692
  method: "POST",
688
693
  headers: {
694
+ ...this.additionalHeaders ?? {},
689
695
  "Content-Type": "application/json;charset=UTF-8",
690
696
  "X-Schematic-Api-Key": this.apiKey
691
697
  },
@@ -791,6 +797,7 @@ var Schematic = class {
791
797
  await fetch(captureUrl, {
792
798
  method: "POST",
793
799
  headers: {
800
+ ...this.additionalHeaders ?? {},
794
801
  "Content-Type": "application/json;charset=UTF-8"
795
802
  },
796
803
  body: payload
@@ -840,8 +847,7 @@ var Schematic = class {
840
847
  wsSendMessage = (socket, context) => {
841
848
  return new Promise((resolve, reject) => {
842
849
  if (contextString(context) == contextString(this.context)) {
843
- resolve();
844
- return;
850
+ return resolve(this.setIsPending(false));
845
851
  }
846
852
  this.context = context;
847
853
  const sendMessage = () => {
@@ -854,7 +860,7 @@ var Schematic = class {
854
860
  (message.flags ?? []).forEach(
855
861
  (flag) => {
856
862
  this.values[contextString(context)][flag.flag] = flag.value;
857
- this.notifyFlagValueListeners(flag.flag);
863
+ this.notifyFlagValueListeners(flag.flag, flag.value);
858
864
  }
859
865
  );
860
866
  if (this.flagListener) {
@@ -898,7 +904,9 @@ var Schematic = class {
898
904
  };
899
905
  setIsPending = (isPending) => {
900
906
  this.isPending = isPending;
901
- this.isPendingListeners.forEach((listener) => listener());
907
+ this.isPendingListeners.forEach(
908
+ (listener) => notifyListener(listener, isPending)
909
+ );
902
910
  };
903
911
  // flagValues state
904
912
  getFlagValue = (flagKey) => {
@@ -918,9 +926,16 @@ var Schematic = class {
918
926
  this.flagValueListeners[flagKey].delete(listener);
919
927
  };
920
928
  };
921
- notifyFlagValueListeners = (flagKey) => {
929
+ notifyFlagValueListeners = (flagKey, value) => {
922
930
  const listeners = this.flagValueListeners?.[flagKey] ?? [];
923
- listeners.forEach((listener) => listener());
931
+ listeners.forEach((listener) => notifyListener(listener, value));
924
932
  };
925
933
  };
934
+ var notifyListener = (listener, value) => {
935
+ if (listener.length > 0) {
936
+ listener(value);
937
+ } else {
938
+ listener();
939
+ }
940
+ };
926
941
  /* @preserve */
@@ -1,9 +1,13 @@
1
+ export declare type BooleanListenerFn = (value: boolean) => void;
2
+
1
3
  export declare type CheckOptions = {
2
4
  context?: SchematicContext;
3
5
  fallback?: boolean;
4
6
  key: string;
5
7
  };
6
8
 
9
+ export declare type EmptyListenerFn = () => void;
10
+
7
11
  declare type Event_2 = {
8
12
  api_key: string;
9
13
  body: EventBody;
@@ -49,7 +53,10 @@ export declare type FlagCheckWithKeyResponseBody = FlagCheckResponseBody & {
49
53
 
50
54
  export declare type Keys = Record<string, string>;
51
55
 
56
+ export declare type ListenerFn = BooleanListenerFn | EmptyListenerFn;
57
+
52
58
  export declare class Schematic {
59
+ private additionalHeaders;
53
60
  private apiKey;
54
61
  private apiUrl;
55
62
  private conn;
@@ -88,11 +95,11 @@ export declare class Schematic {
88
95
  * State management
89
96
  */
90
97
  getIsPending: () => boolean;
91
- addIsPendingListener: (listener: () => void) => () => void;
98
+ addIsPendingListener: (listener: ListenerFn) => () => void;
92
99
  private setIsPending;
93
100
  getFlagValue: (flagKey: string) => boolean;
94
101
  getFlagValues: () => Record<string, boolean>;
95
- addFlagValueListener: (flagKey: string, listener: () => void) => () => void;
102
+ addFlagValueListener: (flagKey: string, listener: ListenerFn) => () => void;
96
103
  private notifyFlagValueListeners;
97
104
  }
98
105
 
@@ -102,12 +109,13 @@ export declare type SchematicContext = {
102
109
  };
103
110
 
104
111
  export declare type SchematicOptions = {
112
+ additionalHeaders?: Record<string, string>;
105
113
  apiUrl?: string;
106
- webSocketUrl?: string;
107
114
  eventUrl?: string;
108
115
  flagListener?: (values: Record<string, boolean>) => void;
109
116
  storage?: StoragePersister;
110
117
  useWebSocket?: boolean;
118
+ webSocketUrl?: string;
111
119
  };
112
120
 
113
121
  export declare type StoragePersister = {
@@ -597,6 +597,7 @@ function contextString(context) {
597
597
  // src/index.ts
598
598
  var anonymousIdKey = "schematicId";
599
599
  var Schematic = class {
600
+ additionalHeaders = {};
600
601
  apiKey;
601
602
  apiUrl = "https://api.schematichq.com";
602
603
  conn = null;
@@ -616,6 +617,9 @@ var Schematic = class {
616
617
  this.eventQueue = [];
617
618
  this.useWebSocket = options?.useWebSocket ?? false;
618
619
  this.flagListener = options?.flagListener;
620
+ if (options?.additionalHeaders) {
621
+ this.additionalHeaders = options.additionalHeaders;
622
+ }
619
623
  if (options?.storage) {
620
624
  this.storage = options.storage;
621
625
  } else if (typeof localStorage !== "undefined") {
@@ -649,8 +653,9 @@ var Schematic = class {
649
653
  return fetch(requestUrl, {
650
654
  method: "POST",
651
655
  headers: {
652
- "X-Schematic-Api-Key": this.apiKey,
653
- "Content-Type": "application/json;charset=UTF-8"
656
+ ...this.additionalHeaders ?? {},
657
+ "Content-Type": "application/json;charset=UTF-8",
658
+ "X-Schematic-Api-Key": this.apiKey
654
659
  },
655
660
  body: JSON.stringify(context)
656
661
  }).then((response) => {
@@ -673,6 +678,7 @@ var Schematic = class {
673
678
  return fetch(requestUrl, {
674
679
  method: "POST",
675
680
  headers: {
681
+ ...this.additionalHeaders ?? {},
676
682
  "Content-Type": "application/json;charset=UTF-8",
677
683
  "X-Schematic-Api-Key": this.apiKey
678
684
  },
@@ -778,6 +784,7 @@ var Schematic = class {
778
784
  await fetch(captureUrl, {
779
785
  method: "POST",
780
786
  headers: {
787
+ ...this.additionalHeaders ?? {},
781
788
  "Content-Type": "application/json;charset=UTF-8"
782
789
  },
783
790
  body: payload
@@ -827,8 +834,7 @@ var Schematic = class {
827
834
  wsSendMessage = (socket, context) => {
828
835
  return new Promise((resolve, reject) => {
829
836
  if (contextString(context) == contextString(this.context)) {
830
- resolve();
831
- return;
837
+ return resolve(this.setIsPending(false));
832
838
  }
833
839
  this.context = context;
834
840
  const sendMessage = () => {
@@ -841,7 +847,7 @@ var Schematic = class {
841
847
  (message.flags ?? []).forEach(
842
848
  (flag) => {
843
849
  this.values[contextString(context)][flag.flag] = flag.value;
844
- this.notifyFlagValueListeners(flag.flag);
850
+ this.notifyFlagValueListeners(flag.flag, flag.value);
845
851
  }
846
852
  );
847
853
  if (this.flagListener) {
@@ -885,7 +891,9 @@ var Schematic = class {
885
891
  };
886
892
  setIsPending = (isPending) => {
887
893
  this.isPending = isPending;
888
- this.isPendingListeners.forEach((listener) => listener());
894
+ this.isPendingListeners.forEach(
895
+ (listener) => notifyListener(listener, isPending)
896
+ );
889
897
  };
890
898
  // flagValues state
891
899
  getFlagValue = (flagKey) => {
@@ -905,11 +913,18 @@ var Schematic = class {
905
913
  this.flagValueListeners[flagKey].delete(listener);
906
914
  };
907
915
  };
908
- notifyFlagValueListeners = (flagKey) => {
916
+ notifyFlagValueListeners = (flagKey, value) => {
909
917
  const listeners = this.flagValueListeners?.[flagKey] ?? [];
910
- listeners.forEach((listener) => listener());
918
+ listeners.forEach((listener) => notifyListener(listener, value));
911
919
  };
912
920
  };
921
+ var notifyListener = (listener, value) => {
922
+ if (listener.length > 0) {
923
+ listener(value);
924
+ } else {
925
+ listener();
926
+ }
927
+ };
913
928
  export {
914
929
  Schematic
915
930
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schematichq/schematic-js",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "main": "dist/schematic.cjs.js",
5
5
  "module": "dist/schematic.esm.js",
6
6
  "types": "dist/schematic.d.ts",