@schematichq/schematic-js 0.1.8 → 0.1.10

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 i=[];for(let n=0;n<256;++n)i.push((n+256).toString(16).slice(1));function v(n,e=0){return i[n[e+0]]+i[n[e+1]]+i[n[e+2]]+i[n[e+3]]+"-"+i[n[e+4]]+i[n[e+5]]+"-"+i[n[e+6]]+i[n[e+7]]+"-"+i[n[e+8]]+i[n[e+9]]+"-"+i[n[e+10]]+i[n[e+11]]+i[n[e+12]]+i[n[e+13]]+i[n[e+14]]+i[n[e+15]]}var f=typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto),y={randomUUID:f};function k(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=k;var g="schematicId";var l=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()})}async checkFlag(e){let{fallback:t=!1,key:r}=e,o=e.context||this.context;if(this.useWebSocket){let s=this.values[h(o)]??{};return typeof s[r]>"u"?t:s[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(s=>{if(!s.ok)throw new Error("Network response was not ok");return s.json()}).then(s=>s.data.value).catch(s=>(console.error("There was a problem with the fetch operation:",s),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,s)=>(a[s.flag]=s.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(g);if(typeof e<"u")return e;let t=d();return this.storage.setItem(g,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/subscribe`,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=>{(JSON.parse(a.data).flags??[]).forEach(c=>{this.values[h(e)][c.flag]=c.value}),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((s,c)=>(s[c]=n[r][c],s),{});return t[r]=a,t},{});return JSON.stringify(e)}window.Schematic=l;})();
1
+ "use strict";(()=>{var l,f=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(f)}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 m=typeof crypto<"u"&&crypto.randomUUID&&crypto.randomUUID.bind(crypto),y={randomUUID:m};function k(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 h=k;var g="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()})}async checkFlag(e){let{fallback:t=!1,key:r}=e,o=e.context||this.context;if(this.useWebSocket){let i=this.values[c(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 h();let e=this.storage.getItem(g);if(typeof e<"u")return e;let t=h();return this.storage.setItem(g,t),t};handleEvent=(e,t)=>{let r={api_key:this.apiKey,body:t,sent_at:new Date().toISOString(),tracker_event_id:h(),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(c(e)==c(this.context)){t();return}if(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);c(e)in this.values||(this.values[c(e)]={}),(i.flags??[]).forEach(d=>{this.values[c(e)][d.flag]=d.value}),this.flagListener&&this.flagListener(this.values[c(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 c(n){let e=Object.keys(n).reduce((t,r)=>{let a=Object.keys(n[r]||{}).sort().reduce((i,d)=>(i[d]=n[r][d],i),{});return t[r]=a,t},{});return JSON.stringify(e)}window.Schematic=p;})();
2
2
  /* @preserve */
@@ -259,7 +259,7 @@ var Schematic = class {
259
259
  if (this.conn) {
260
260
  resolve();
261
261
  }
262
- const wsUrl = `${this.webSocketUrl}/flags/subscribe`;
262
+ const wsUrl = `${this.webSocketUrl}/flags/bootstrap`;
263
263
  const webSocket = new WebSocket(wsUrl);
264
264
  this.conn = webSocket;
265
265
  webSocket.onopen = () => {
@@ -275,6 +275,7 @@ var Schematic = class {
275
275
  return new Promise((resolve, reject) => {
276
276
  if (contextString(context) == contextString(this.context)) {
277
277
  resolve();
278
+ return;
278
279
  }
279
280
  this.context = context;
280
281
  if (!this.conn) {
@@ -285,9 +286,14 @@ var Schematic = class {
285
286
  let resolved = false;
286
287
  this.conn.onmessage = (event) => {
287
288
  const message = JSON.parse(event.data);
288
- (message.flags ?? []).forEach((flag) => {
289
- this.values[contextString(context)][flag.flag] = flag.value;
290
- });
289
+ if (!(contextString(context) in this.values)) {
290
+ this.values[contextString(context)] = {};
291
+ }
292
+ (message.flags ?? []).forEach(
293
+ (flag) => {
294
+ this.values[contextString(context)][flag.flag] = flag.value;
295
+ }
296
+ );
291
297
  if (this.flagListener) {
292
298
  this.flagListener(this.values[contextString(context)]);
293
299
  }
@@ -233,7 +233,7 @@ var Schematic = class {
233
233
  if (this.conn) {
234
234
  resolve();
235
235
  }
236
- const wsUrl = `${this.webSocketUrl}/flags/subscribe`;
236
+ const wsUrl = `${this.webSocketUrl}/flags/bootstrap`;
237
237
  const webSocket = new WebSocket(wsUrl);
238
238
  this.conn = webSocket;
239
239
  webSocket.onopen = () => {
@@ -249,6 +249,7 @@ var Schematic = class {
249
249
  return new Promise((resolve, reject) => {
250
250
  if (contextString(context) == contextString(this.context)) {
251
251
  resolve();
252
+ return;
252
253
  }
253
254
  this.context = context;
254
255
  if (!this.conn) {
@@ -259,9 +260,14 @@ var Schematic = class {
259
260
  let resolved = false;
260
261
  this.conn.onmessage = (event) => {
261
262
  const message = JSON.parse(event.data);
262
- (message.flags ?? []).forEach((flag) => {
263
- this.values[contextString(context)][flag.flag] = flag.value;
264
- });
263
+ if (!(contextString(context) in this.values)) {
264
+ this.values[contextString(context)] = {};
265
+ }
266
+ (message.flags ?? []).forEach(
267
+ (flag) => {
268
+ this.values[contextString(context)][flag.flag] = flag.value;
269
+ }
270
+ );
265
271
  if (this.flagListener) {
266
272
  this.flagListener(this.values[contextString(context)]);
267
273
  }
package/package.json CHANGED
@@ -19,6 +19,7 @@
19
19
  "jest-environment-jsdom": "^29.7.0",
20
20
  "jest-esbuild": "^0.3.0",
21
21
  "jest-fetch-mock": "^3.0.3",
22
+ "prettier": "^3.3.1",
22
23
  "ts-jest": "^29.1.1",
23
24
  "typescript": "^5.0.2"
24
25
  },
@@ -40,9 +41,10 @@
40
41
  "build:esm": "npx esbuild src/index.ts --bundle --format=esm --outfile=dist/schematic.esm.js",
41
42
  "build:types": "npx tsc && npx api-extractor run",
42
43
  "clean": "rm -rf dist",
44
+ "format": "prettier --write src/*.ts",
43
45
  "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --fix",
44
46
  "test": "jest --config jest.config.js"
45
47
  },
46
48
  "types": "dist/schematic.d.ts",
47
- "version": "0.1.8"
49
+ "version": "0.1.10"
48
50
  }