@schematichq/schematic-js 0.1.4 → 0.1.6

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,2 +1,2 @@
1
- "use strict";(()=>{var p,m=new Uint8Array(16);function u(){if(!p&&(p=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!p))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return p(m)}var s=[];for(let n=0;n<256;++n)s.push((n+256).toString(16).slice(1));function v(n,e=0){return s[n[e+0]]+s[n[e+1]]+s[n[e+2]]+s[n[e+3]]+"-"+s[n[e+4]]+s[n[e+5]]+"-"+s[n[e+6]]+s[n[e+7]]+"-"+s[n[e+8]]+s[n[e+9]]+"-"+s[n[e+10]]+s[n[e+11]]+s[n[e+12]]+s[n[e+13]]+s[n[e+14]]+s[n[e+15]]}var k=typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto),y={randomUUID:k};function S(n,e,t){if(y.randomUUID&&!e&&!n)return y.randomUUID();n=n||{};let r=n.random||(n.rng||u)();if(r[6]=r[6]&15|64,r[8]=r[8]&63|128,e){t=t||0;for(let o=0;o<16;++o)e[t+o]=r[o];return e}return v(r)}var d=S;var f="schematicId";var l=class{apiKey;apiUrl="api.schematichq.com";eventUrl="c.schematichq.com";conn=null;context={};eventQueue;storage;useWebSocket=!1;values={};flagListener;constructor(e,t){this.apiKey=e,this.eventQueue=[],this.useWebSocket=t?.useWebSocket??!1,this.flagListener=t?.flagListener,t?.storage?this.storage=t.storage:typeof localStorage<"u"&&(this.storage=localStorage),t?.apiUrl!==void 0&&(this.apiUrl=t.apiUrl),t?.eventUrl!==void 0&&(this.eventUrl=t.eventUrl),typeof window<"u"&&window.addEventListener("beforeunload",()=>{this.flushEventQueue()})}checkFlag=async e=>{let{fallback:t=!1,key:r}=e,o=e.context||this.context;if(this.useWebSocket){let i=this.values[h(o)]??{};return typeof i[r]>"u"?t:i[r]}let a=this.getUrl(this.apiUrl,`flags/${r}/check`);return fetch(a,{method:"POST",headers:{"X-Schematic-Api-Key":this.apiKey,"Content-Type":"application/json;charset=UTF-8"},body:JSON.stringify(o)}).then(i=>{if(!i.ok)throw new Error("Network response was not ok");return i.json()}).then(i=>i.data.value).catch(i=>(console.error("There was a problem with the fetch operation:",i),t))};checkFlags=async e=>{e=e||this.context;let t=this.getUrl(this.apiUrl,"flags/check"),r=JSON.stringify(e);return fetch(t,{method:"POST",headers:{"Content-Type":"application/json;charset=UTF-8","X-Schematic-Api-Key":this.apiKey},body:r}).then(o=>{if(!o.ok)throw new Error("Network response was not ok");return o.json()}).then(o=>(o?.data?.flags??[]).reduce((a,i)=>(a[i.flag]=i.value,a),{})).catch(o=>(console.error("There was a problem with the fetch operation:",o),!1))};cleanup=()=>{this.conn&&this.conn.close()};identify=e=>{this.handleEvent("identify",e)};setContext=e=>this.useWebSocket?new Promise(t=>{this.wsConnect().then(()=>{this.wsSendMessage(e),t()})}):(this.context=e,Promise.resolve());track=e=>{this.handleEvent("track",e)};getUrl=(e,t,r)=>{let o="http";return r==="ws"&&(o="ws"),typeof window>"u"||window.location.protocol==="https:"?`${o}s://${e}/${t}`:`${o}://${e}/${t}`};flushEventQueue=()=>{for(;this.eventQueue.length>0;){let e=this.eventQueue.shift();e&&this.sendEvent(e)}};getAnonymousId=()=>{if(!this.storage)return d();let e=this.storage.getItem(f);if(typeof e<"u")return e;let t=d();return this.storage.setItem(f,t),t};handleEvent=(e,t)=>{let r={api_key:this.apiKey,body:t,sent_at:new Date().toISOString(),tracker_event_id:d(),tracker_user_id:this.getAnonymousId(),type:e};typeof document<"u"&&document.hidden?this.storeEvent(r):this.sendEvent(r)};sendEvent=e=>{let t=this.getUrl(this.eventUrl,"e"),r=JSON.stringify(e);fetch(t,{method:"POST",headers:{"Content-Type":"application/json;charset=UTF-8"},body:r}).then(o=>{if(!o.ok)throw new Error(`Network response was not ok: ${o.statusText}`)}).catch(o=>{console.error("There was a problem with the fetch operation:",o)})};storeEvent=e=>{this.eventQueue.push(e)};wsConnect=()=>new Promise(e=>{this.conn&&e();let t=this.getUrl(this.apiUrl,"flags/bootstrap","ws"),r=new WebSocket(t);this.conn=r,r.onopen=()=>{e()},r.onclose=()=>{this.conn=null}});wsSendMessage=e=>new Promise((t,r)=>{if(h(e)==h(this.context)&&t(),this.context=e,!this.conn){r("Not connected");return}if(this.conn.readyState===WebSocket.OPEN){let o=!1;this.conn.onmessage=a=>{let i=JSON.parse(a.data);this.values[h(e)]=(i.flags??[]).reduce((c,g)=>(c[g.flag]=g.value,c),{}),this.flagListener&&this.flagListener(this.values[h(e)]),o||(o=!0,t())},this.conn.onerror=a=>{console.error("Schematic websocket error: ",a)},this.conn.send(JSON.stringify({apiKey:this.apiKey,data:e}))}else this.conn.readyState===WebSocket.CONNECTING?this.conn.onopen=()=>{this.wsSendMessage(e)}:r("Not connected")})};function h(n){let e=Object.keys(n).reduce((t,r)=>{let a=Object.keys(n[r]||{}).sort().reduce((i,c)=>(i[c]=n[r][c],i),{});return t[r]=a,t},{});return JSON.stringify(e)}window.Schematic=l;})();
1
+ "use strict";(()=>{var l,m=new Uint8Array(16);function u(){if(!l&&(l=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!l))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return l(m)}var s=[];for(let n=0;n<256;++n)s.push((n+256).toString(16).slice(1));function g(n,e=0){return s[n[e+0]]+s[n[e+1]]+s[n[e+2]]+s[n[e+3]]+"-"+s[n[e+4]]+s[n[e+5]]+"-"+s[n[e+6]]+s[n[e+7]]+"-"+s[n[e+8]]+s[n[e+9]]+"-"+s[n[e+10]]+s[n[e+11]]+s[n[e+12]]+s[n[e+13]]+s[n[e+14]]+s[n[e+15]]}var k=typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto),y={randomUUID:k};function S(n,e,t){if(y.randomUUID&&!e&&!n)return y.randomUUID();n=n||{};let r=n.random||(n.rng||u)();if(r[6]=r[6]&15|64,r[8]=r[8]&63|128,e){t=t||0;for(let o=0;o<16;++o)e[t+o]=r[o];return e}return g(r)}var d=S;var f="schematicId";var p=class{apiKey;apiUrl="https://api.schematichq.com";webSocketUrl="wss://api.schematichq.com";eventUrl="https://c.schematichq.com";conn=null;context={};eventQueue;storage;useWebSocket=!1;values={};flagListener;constructor(e,t){this.apiKey=e,this.eventQueue=[],this.useWebSocket=t?.useWebSocket??!1,this.flagListener=t?.flagListener,t?.storage?this.storage=t.storage:typeof localStorage<"u"&&(this.storage=localStorage),t?.apiUrl!==void 0&&(this.apiUrl=t.apiUrl),t?.eventUrl!==void 0&&(this.eventUrl=t.eventUrl),t?.webSocketUrl!==void 0&&(this.webSocketUrl=t.webSocketUrl),window?.addEventListener&&window.addEventListener("beforeunload",()=>{this.flushEventQueue()})}checkFlag=async e=>{let{fallback:t=!1,key:r}=e,o=e.context||this.context;if(this.useWebSocket){let i=this.values[h(o)]??{};return typeof i[r]>"u"?t:i[r]}let a=`${this.apiUrl}/flags/${r}/check`;return fetch(a,{method:"POST",headers:{"X-Schematic-Api-Key":this.apiKey,"Content-Type":"application/json;charset=UTF-8"},body:JSON.stringify(o)}).then(i=>{if(!i.ok)throw new Error("Network response was not ok");return i.json()}).then(i=>i.data.value).catch(i=>(console.error("There was a problem with the fetch operation:",i),t))};checkFlags=async e=>{e=e||this.context;let t=`${this.apiUrl}/flags/check`,r=JSON.stringify(e);return fetch(t,{method:"POST",headers:{"Content-Type":"application/json;charset=UTF-8","X-Schematic-Api-Key":this.apiKey},body:r}).then(o=>{if(!o.ok)throw new Error("Network response was not ok");return o.json()}).then(o=>(o?.data?.flags??[]).reduce((a,i)=>(a[i.flag]=i.value,a),{})).catch(o=>(console.error("There was a problem with the fetch operation:",o),!1))};cleanup=()=>{this.conn&&this.conn.close()};identify=e=>{this.handleEvent("identify",e)};setContext=e=>this.useWebSocket?new Promise(t=>{this.wsConnect().then(()=>{this.wsSendMessage(e),t()})}):(this.context=e,Promise.resolve());track=e=>{this.handleEvent("track",e)};flushEventQueue=()=>{for(;this.eventQueue.length>0;){let e=this.eventQueue.shift();e&&this.sendEvent(e)}};getAnonymousId=()=>{if(!this.storage)return d();let e=this.storage.getItem(f);if(typeof e<"u")return e;let t=d();return this.storage.setItem(f,t),t};handleEvent=(e,t)=>{let r={api_key:this.apiKey,body:t,sent_at:new Date().toISOString(),tracker_event_id:d(),tracker_user_id:this.getAnonymousId(),type:e};document?.hidden?this.storeEvent(r):this.sendEvent(r)};sendEvent=e=>{let t=`${this.eventUrl}/e`,r=JSON.stringify(e);fetch(t,{method:"POST",headers:{"Content-Type":"application/json;charset=UTF-8"},body:r}).then(o=>{if(!o.ok)throw new Error(`Network response was not ok: ${o.statusText}`)}).catch(o=>{console.error("There was a problem with the fetch operation:",o)})};storeEvent=e=>{this.eventQueue.push(e)};wsConnect=()=>new Promise(e=>{this.conn&&e();let t=`${this.webSocketUrl}/flags/bootstrap`,r=new WebSocket(t);this.conn=r,r.onopen=()=>{e()},r.onclose=()=>{this.conn=null}});wsSendMessage=e=>new Promise((t,r)=>{if(h(e)==h(this.context)&&t(),this.context=e,!this.conn){r("Not connected");return}if(this.conn.readyState===WebSocket.OPEN){let o=!1;this.conn.onmessage=a=>{let i=JSON.parse(a.data);this.values[h(e)]=(i.flags??[]).reduce((c,v)=>(c[v.flag]=v.value,c),{}),this.flagListener&&this.flagListener(this.values[h(e)]),o||(o=!0,t())},this.conn.onerror=a=>{console.error("Schematic websocket error: ",a)},this.conn.send(JSON.stringify({apiKey:this.apiKey,data:e}))}else this.conn.readyState===WebSocket.CONNECTING?this.conn.onopen=()=>{this.wsSendMessage(e)}:r("Not connected")})};function h(n){let e=Object.keys(n).reduce((t,r)=>{let a=Object.keys(n[r]||{}).sort().reduce((i,c)=>(i[c]=n[r][c],i),{});return t[r]=a,t},{});return JSON.stringify(e)}window.Schematic=p;})();
2
2
  /* @preserve */
@@ -76,8 +76,9 @@ var v4_default = v4;
76
76
  var anonymousIdKey = "schematicId";
77
77
  var Schematic = class {
78
78
  apiKey;
79
- apiUrl = "api.schematichq.com";
80
- eventUrl = "c.schematichq.com";
79
+ apiUrl = "https://api.schematichq.com";
80
+ webSocketUrl = "wss://api.schematichq.com";
81
+ eventUrl = "https://c.schematichq.com";
81
82
  conn = null;
82
83
  context = {};
83
84
  eventQueue;
@@ -101,7 +102,10 @@ var Schematic = class {
101
102
  if (options?.eventUrl !== void 0) {
102
103
  this.eventUrl = options.eventUrl;
103
104
  }
104
- if (typeof window !== "undefined") {
105
+ if (options?.webSocketUrl !== void 0) {
106
+ this.webSocketUrl = options.webSocketUrl;
107
+ }
108
+ if (window?.addEventListener) {
105
109
  window.addEventListener("beforeunload", () => {
106
110
  this.flushEventQueue();
107
111
  });
@@ -114,7 +118,7 @@ var Schematic = class {
114
118
  const contextVals = this.values[contextString(context)] ?? {};
115
119
  return typeof contextVals[key] === "undefined" ? fallback : contextVals[key];
116
120
  }
117
- const requestUrl = this.getUrl(this.apiUrl, `flags/${key}/check`);
121
+ const requestUrl = `${this.apiUrl}/flags/${key}/check`;
118
122
  return fetch(requestUrl, {
119
123
  method: "POST",
120
124
  headers: {
@@ -137,7 +141,7 @@ var Schematic = class {
137
141
  // Make a REST API call to fetch all flag values for a given context
138
142
  checkFlags = async (context) => {
139
143
  context = context || this.context;
140
- const requestUrl = this.getUrl(this.apiUrl, "flags/check");
144
+ const requestUrl = `${this.apiUrl}/flags/check`;
141
145
  const requestBody = JSON.stringify(context);
142
146
  return fetch(requestUrl, {
143
147
  method: "POST",
@@ -193,16 +197,6 @@ var Schematic = class {
193
197
  track = (body) => {
194
198
  this.handleEvent("track", body);
195
199
  };
196
- getUrl = (domain, path, urlType) => {
197
- let scheme = "http";
198
- if (urlType === "ws") {
199
- scheme = "ws";
200
- }
201
- if (typeof window === "undefined" || window.location.protocol === "https:") {
202
- return `${scheme}s://${domain}/${path}`;
203
- }
204
- return `${scheme}://${domain}/${path}`;
205
- };
206
200
  flushEventQueue = () => {
207
201
  while (this.eventQueue.length > 0) {
208
202
  const event = this.eventQueue.shift();
@@ -232,14 +226,14 @@ var Schematic = class {
232
226
  tracker_user_id: this.getAnonymousId(),
233
227
  type: eventType
234
228
  };
235
- if (typeof document !== "undefined" && document.hidden) {
229
+ if (document?.hidden) {
236
230
  this.storeEvent(event);
237
231
  } else {
238
232
  this.sendEvent(event);
239
233
  }
240
234
  };
241
235
  sendEvent = (event) => {
242
- const captureUrl = this.getUrl(this.eventUrl, "e");
236
+ const captureUrl = `${this.eventUrl}/e`;
243
237
  const payload = JSON.stringify(event);
244
238
  fetch(captureUrl, {
245
239
  method: "POST",
@@ -265,7 +259,7 @@ var Schematic = class {
265
259
  if (this.conn) {
266
260
  resolve();
267
261
  }
268
- const wsUrl = this.getUrl(this.apiUrl, "flags/bootstrap", "ws");
262
+ const wsUrl = `${this.webSocketUrl}/flags/bootstrap`;
269
263
  const webSocket = new WebSocket(wsUrl);
270
264
  this.conn = webSocket;
271
265
  webSocket.onopen = () => {
@@ -54,6 +54,7 @@ export declare type Keys = Record<string, string>;
54
54
  export declare class Schematic {
55
55
  private apiKey;
56
56
  private apiUrl;
57
+ private webSocketUrl;
57
58
  private eventUrl;
58
59
  private conn;
59
60
  private context;
@@ -69,7 +70,6 @@ export declare class Schematic {
69
70
  identify: (body: EventBodyIdentify) => void;
70
71
  setContext: (context: SchematicContext) => Promise<void>;
71
72
  track: (body: EventBodyTrack) => void;
72
- private getUrl;
73
73
  private flushEventQueue;
74
74
  private getAnonymousId;
75
75
  private handleEvent;
@@ -86,6 +86,7 @@ export declare type SchematicContext = {
86
86
 
87
87
  declare type SchematicOptions = {
88
88
  apiUrl?: string;
89
+ webSocketUrl?: string;
89
90
  eventUrl?: string;
90
91
  flagListener?: (values: Record<string, boolean>) => void;
91
92
  storage?: StoragePersister;
@@ -50,8 +50,9 @@ var v4_default = v4;
50
50
  var anonymousIdKey = "schematicId";
51
51
  var Schematic = class {
52
52
  apiKey;
53
- apiUrl = "api.schematichq.com";
54
- eventUrl = "c.schematichq.com";
53
+ apiUrl = "https://api.schematichq.com";
54
+ webSocketUrl = "wss://api.schematichq.com";
55
+ eventUrl = "https://c.schematichq.com";
55
56
  conn = null;
56
57
  context = {};
57
58
  eventQueue;
@@ -75,7 +76,10 @@ var Schematic = class {
75
76
  if (options?.eventUrl !== void 0) {
76
77
  this.eventUrl = options.eventUrl;
77
78
  }
78
- if (typeof window !== "undefined") {
79
+ if (options?.webSocketUrl !== void 0) {
80
+ this.webSocketUrl = options.webSocketUrl;
81
+ }
82
+ if (window?.addEventListener) {
79
83
  window.addEventListener("beforeunload", () => {
80
84
  this.flushEventQueue();
81
85
  });
@@ -88,7 +92,7 @@ var Schematic = class {
88
92
  const contextVals = this.values[contextString(context)] ?? {};
89
93
  return typeof contextVals[key] === "undefined" ? fallback : contextVals[key];
90
94
  }
91
- const requestUrl = this.getUrl(this.apiUrl, `flags/${key}/check`);
95
+ const requestUrl = `${this.apiUrl}/flags/${key}/check`;
92
96
  return fetch(requestUrl, {
93
97
  method: "POST",
94
98
  headers: {
@@ -111,7 +115,7 @@ var Schematic = class {
111
115
  // Make a REST API call to fetch all flag values for a given context
112
116
  checkFlags = async (context) => {
113
117
  context = context || this.context;
114
- const requestUrl = this.getUrl(this.apiUrl, "flags/check");
118
+ const requestUrl = `${this.apiUrl}/flags/check`;
115
119
  const requestBody = JSON.stringify(context);
116
120
  return fetch(requestUrl, {
117
121
  method: "POST",
@@ -167,16 +171,6 @@ var Schematic = class {
167
171
  track = (body) => {
168
172
  this.handleEvent("track", body);
169
173
  };
170
- getUrl = (domain, path, urlType) => {
171
- let scheme = "http";
172
- if (urlType === "ws") {
173
- scheme = "ws";
174
- }
175
- if (typeof window === "undefined" || window.location.protocol === "https:") {
176
- return `${scheme}s://${domain}/${path}`;
177
- }
178
- return `${scheme}://${domain}/${path}`;
179
- };
180
174
  flushEventQueue = () => {
181
175
  while (this.eventQueue.length > 0) {
182
176
  const event = this.eventQueue.shift();
@@ -206,14 +200,14 @@ var Schematic = class {
206
200
  tracker_user_id: this.getAnonymousId(),
207
201
  type: eventType
208
202
  };
209
- if (typeof document !== "undefined" && document.hidden) {
203
+ if (document?.hidden) {
210
204
  this.storeEvent(event);
211
205
  } else {
212
206
  this.sendEvent(event);
213
207
  }
214
208
  };
215
209
  sendEvent = (event) => {
216
- const captureUrl = this.getUrl(this.eventUrl, "e");
210
+ const captureUrl = `${this.eventUrl}/e`;
217
211
  const payload = JSON.stringify(event);
218
212
  fetch(captureUrl, {
219
213
  method: "POST",
@@ -239,7 +233,7 @@ var Schematic = class {
239
233
  if (this.conn) {
240
234
  resolve();
241
235
  }
242
- const wsUrl = this.getUrl(this.apiUrl, "flags/bootstrap", "ws");
236
+ const wsUrl = `${this.webSocketUrl}/flags/bootstrap`;
243
237
  const webSocket = new WebSocket(wsUrl);
244
238
  this.conn = webSocket;
245
239
  webSocket.onopen = () => {
package/package.json CHANGED
@@ -44,5 +44,5 @@
44
44
  "test": "jest --config jest.config.js"
45
45
  },
46
46
  "types": "dist/schematic.d.ts",
47
- "version": "0.1.4"
47
+ "version": "0.1.6"
48
48
  }