@schematichq/schematic-js 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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)){i();return}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
@@ -854,7 +861,7 @@ var Schematic = class {
854
861
  (message.flags ?? []).forEach(
855
862
  (flag) => {
856
863
  this.values[contextString(context)][flag.flag] = flag.value;
857
- this.notifyFlagValueListeners(flag.flag);
864
+ this.notifyFlagValueListeners(flag.flag, flag.value);
858
865
  }
859
866
  );
860
867
  if (this.flagListener) {
@@ -898,7 +905,9 @@ var Schematic = class {
898
905
  };
899
906
  setIsPending = (isPending) => {
900
907
  this.isPending = isPending;
901
- this.isPendingListeners.forEach((listener) => listener());
908
+ this.isPendingListeners.forEach(
909
+ (listener) => notifyListener(listener, isPending)
910
+ );
902
911
  };
903
912
  // flagValues state
904
913
  getFlagValue = (flagKey) => {
@@ -918,9 +927,16 @@ var Schematic = class {
918
927
  this.flagValueListeners[flagKey].delete(listener);
919
928
  };
920
929
  };
921
- notifyFlagValueListeners = (flagKey) => {
930
+ notifyFlagValueListeners = (flagKey, value) => {
922
931
  const listeners = this.flagValueListeners?.[flagKey] ?? [];
923
- listeners.forEach((listener) => listener());
932
+ listeners.forEach((listener) => notifyListener(listener, value));
924
933
  };
925
934
  };
935
+ var notifyListener = (listener, value) => {
936
+ if (listener.length > 0) {
937
+ listener(value);
938
+ } else {
939
+ listener();
940
+ }
941
+ };
926
942
  /* @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
@@ -841,7 +848,7 @@ var Schematic = class {
841
848
  (message.flags ?? []).forEach(
842
849
  (flag) => {
843
850
  this.values[contextString(context)][flag.flag] = flag.value;
844
- this.notifyFlagValueListeners(flag.flag);
851
+ this.notifyFlagValueListeners(flag.flag, flag.value);
845
852
  }
846
853
  );
847
854
  if (this.flagListener) {
@@ -885,7 +892,9 @@ var Schematic = class {
885
892
  };
886
893
  setIsPending = (isPending) => {
887
894
  this.isPending = isPending;
888
- this.isPendingListeners.forEach((listener) => listener());
895
+ this.isPendingListeners.forEach(
896
+ (listener) => notifyListener(listener, isPending)
897
+ );
889
898
  };
890
899
  // flagValues state
891
900
  getFlagValue = (flagKey) => {
@@ -905,11 +914,18 @@ var Schematic = class {
905
914
  this.flagValueListeners[flagKey].delete(listener);
906
915
  };
907
916
  };
908
- notifyFlagValueListeners = (flagKey) => {
917
+ notifyFlagValueListeners = (flagKey, value) => {
909
918
  const listeners = this.flagValueListeners?.[flagKey] ?? [];
910
- listeners.forEach((listener) => listener());
919
+ listeners.forEach((listener) => notifyListener(listener, value));
911
920
  };
912
921
  };
922
+ var notifyListener = (listener, value) => {
923
+ if (listener.length > 0) {
924
+ listener(value);
925
+ } else {
926
+ listener();
927
+ }
928
+ };
913
929
  export {
914
930
  Schematic
915
931
  };
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.1",
4
4
  "main": "dist/schematic.cjs.js",
5
5
  "module": "dist/schematic.esm.js",
6
6
  "types": "dist/schematic.d.ts",