@schematichq/schematic-js 0.1.10 → 0.1.11

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 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;})();
1
+ "use strict";(()=>{var u,g=new Uint8Array(16);function p(){if(!u&&(u=typeof crypto<"u"&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto),!u))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return u(g)}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 S(n,e,t){if(y.randomUUID&&!e&&!n)return y.randomUUID();n=n||{};let r=n.random||(n.rng||p)();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=S;var m="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[c(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.setContext({company:e.company?.keys,user:e.keys}),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=>{let{company:t,user:r,event:o,traits:a}=e;return this.handleEvent("track",{company:t??this.context.company,event:o,traits:a??{},user:r??this.context.user})};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(m);if(typeof e<"u")return e;let t=h();return this.storage.setItem(m,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};return document?.hidden?this.storeEvent(r):this.sendEvent(r)};sendEvent=async e=>{let t=`${this.eventUrl}/e`,r=JSON.stringify(e);try{await fetch(t,{method:"POST",headers:{"Content-Type":"application/json;charset=UTF-8"},body:r})}catch(o){console.error("Error sending Schematic event: ",o)}return Promise.resolve()};storeEvent=e=>(this.eventQueue.push(e),Promise.resolve());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 s=JSON.parse(a.data);c(e)in this.values||(this.values[c(e)]={}),(s.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((s,d)=>(s[d]=n[r][d],s),{});return t[r]=a,t},{});return JSON.stringify(e)}window.Schematic=l;})();
2
2
  /* @preserve */
@@ -175,7 +175,11 @@ var Schematic = class {
175
175
  };
176
176
  // Send an identify event
177
177
  identify = (body) => {
178
- this.handleEvent("identify", body);
178
+ this.setContext({
179
+ company: body.company?.keys,
180
+ user: body.keys
181
+ });
182
+ return this.handleEvent("identify", body);
179
183
  };
180
184
  // Set the flag evaluation context; if the context has changed,
181
185
  // this will open a websocket connection (if not already open)
@@ -195,7 +199,13 @@ var Schematic = class {
195
199
  };
196
200
  // Send track event
197
201
  track = (body) => {
198
- this.handleEvent("track", body);
202
+ const { company, user, event, traits } = body;
203
+ return this.handleEvent("track", {
204
+ company: company ?? this.context.company,
205
+ event,
206
+ traits: traits ?? {},
207
+ user: user ?? this.context.user
208
+ });
199
209
  };
200
210
  flushEventQueue = () => {
201
211
  while (this.eventQueue.length > 0) {
@@ -227,32 +237,30 @@ var Schematic = class {
227
237
  type: eventType
228
238
  };
229
239
  if (document?.hidden) {
230
- this.storeEvent(event);
240
+ return this.storeEvent(event);
231
241
  } else {
232
- this.sendEvent(event);
242
+ return this.sendEvent(event);
233
243
  }
234
244
  };
235
- sendEvent = (event) => {
245
+ sendEvent = async (event) => {
236
246
  const captureUrl = `${this.eventUrl}/e`;
237
247
  const payload = JSON.stringify(event);
238
- fetch(captureUrl, {
239
- method: "POST",
240
- headers: {
241
- "Content-Type": "application/json;charset=UTF-8"
242
- },
243
- body: payload
244
- }).then((response) => {
245
- if (!response.ok) {
246
- throw new Error(
247
- `Network response was not ok: ${response.statusText}`
248
- );
249
- }
250
- }).catch((error) => {
251
- console.error("There was a problem with the fetch operation:", error);
252
- });
248
+ try {
249
+ await fetch(captureUrl, {
250
+ method: "POST",
251
+ headers: {
252
+ "Content-Type": "application/json;charset=UTF-8"
253
+ },
254
+ body: payload
255
+ });
256
+ } catch (error) {
257
+ console.error("Error sending Schematic event: ", error);
258
+ }
259
+ return Promise.resolve();
253
260
  };
254
261
  storeEvent = (event) => {
255
262
  this.eventQueue.push(event);
263
+ return Promise.resolve();
256
264
  };
257
265
  wsConnect = () => {
258
266
  return new Promise((resolve) => {
@@ -16,22 +16,20 @@ export { Event_2 as Event }
16
16
 
17
17
  export declare type EventBody = EventBodyIdentify | EventBodyTrack;
18
18
 
19
- export declare type EventBodyCompany = {
20
- keys: Keys;
21
- name?: string;
22
- traits: Traits;
23
- };
24
-
25
19
  export declare type EventBodyIdentify = {
26
- company?: EventBodyCompany;
27
- keys: Keys;
20
+ company?: {
21
+ keys?: Keys;
22
+ name?: string;
23
+ traits?: Traits;
24
+ };
25
+ keys?: Keys;
28
26
  name?: string;
29
- traits: Traits;
27
+ traits?: Traits;
30
28
  };
31
29
 
32
30
  export declare type EventBodyTrack = SchematicContext & {
33
31
  event: string;
34
- traits: Traits;
32
+ traits?: Traits;
35
33
  };
36
34
 
37
35
  export declare type EventType = "identify" | "track";
@@ -67,9 +65,9 @@ export declare class Schematic {
67
65
  checkFlag(options: CheckOptions): Promise<boolean>;
68
66
  checkFlags: (context?: SchematicContext) => Promise<Record<string, boolean>>;
69
67
  cleanup: () => void;
70
- identify: (body: EventBodyIdentify) => void;
68
+ identify: (body: EventBodyIdentify) => Promise<void>;
71
69
  setContext: (context: SchematicContext) => Promise<void>;
72
- track: (body: EventBodyTrack) => void;
70
+ track: (body: EventBodyTrack) => Promise<void>;
73
71
  private flushEventQueue;
74
72
  private getAnonymousId;
75
73
  private handleEvent;
@@ -149,7 +149,11 @@ var Schematic = class {
149
149
  };
150
150
  // Send an identify event
151
151
  identify = (body) => {
152
- this.handleEvent("identify", body);
152
+ this.setContext({
153
+ company: body.company?.keys,
154
+ user: body.keys
155
+ });
156
+ return this.handleEvent("identify", body);
153
157
  };
154
158
  // Set the flag evaluation context; if the context has changed,
155
159
  // this will open a websocket connection (if not already open)
@@ -169,7 +173,13 @@ var Schematic = class {
169
173
  };
170
174
  // Send track event
171
175
  track = (body) => {
172
- this.handleEvent("track", body);
176
+ const { company, user, event, traits } = body;
177
+ return this.handleEvent("track", {
178
+ company: company ?? this.context.company,
179
+ event,
180
+ traits: traits ?? {},
181
+ user: user ?? this.context.user
182
+ });
173
183
  };
174
184
  flushEventQueue = () => {
175
185
  while (this.eventQueue.length > 0) {
@@ -201,32 +211,30 @@ var Schematic = class {
201
211
  type: eventType
202
212
  };
203
213
  if (document?.hidden) {
204
- this.storeEvent(event);
214
+ return this.storeEvent(event);
205
215
  } else {
206
- this.sendEvent(event);
216
+ return this.sendEvent(event);
207
217
  }
208
218
  };
209
- sendEvent = (event) => {
219
+ sendEvent = async (event) => {
210
220
  const captureUrl = `${this.eventUrl}/e`;
211
221
  const payload = JSON.stringify(event);
212
- fetch(captureUrl, {
213
- method: "POST",
214
- headers: {
215
- "Content-Type": "application/json;charset=UTF-8"
216
- },
217
- body: payload
218
- }).then((response) => {
219
- if (!response.ok) {
220
- throw new Error(
221
- `Network response was not ok: ${response.statusText}`
222
- );
223
- }
224
- }).catch((error) => {
225
- console.error("There was a problem with the fetch operation:", error);
226
- });
222
+ try {
223
+ await fetch(captureUrl, {
224
+ method: "POST",
225
+ headers: {
226
+ "Content-Type": "application/json;charset=UTF-8"
227
+ },
228
+ body: payload
229
+ });
230
+ } catch (error) {
231
+ console.error("Error sending Schematic event: ", error);
232
+ }
233
+ return Promise.resolve();
227
234
  };
228
235
  storeEvent = (event) => {
229
236
  this.eventQueue.push(event);
237
+ return Promise.resolve();
230
238
  };
231
239
  wsConnect = () => {
232
240
  return new Promise((resolve) => {
package/package.json CHANGED
@@ -46,5 +46,5 @@
46
46
  "test": "jest --config jest.config.js"
47
47
  },
48
48
  "types": "dist/schematic.d.ts",
49
- "version": "0.1.10"
49
+ "version": "0.1.11"
50
50
  }