@schematichq/schematic-js 1.0.3 → 1.1.0

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.
@@ -29,11 +29,12 @@ var require_browser_polyfill = __commonJS({
29
29
  "node_modules/cross-fetch/dist/browser-polyfill.js"(exports) {
30
30
  (function(self2) {
31
31
  var irrelevant = function(exports2) {
32
- var global = typeof globalThis !== "undefined" && globalThis || typeof self2 !== "undefined" && self2 || typeof global !== "undefined" && global;
32
+ var g = typeof globalThis !== "undefined" && globalThis || typeof self2 !== "undefined" && self2 || // eslint-disable-next-line no-undef
33
+ typeof global !== "undefined" && global || {};
33
34
  var support = {
34
- searchParams: "URLSearchParams" in global,
35
- iterable: "Symbol" in global && "iterator" in Symbol,
36
- blob: "FileReader" in global && "Blob" in global && function() {
35
+ searchParams: "URLSearchParams" in g,
36
+ iterable: "Symbol" in g && "iterator" in Symbol,
37
+ blob: "FileReader" in g && "Blob" in g && function() {
37
38
  try {
38
39
  new Blob();
39
40
  return true;
@@ -41,8 +42,8 @@ var require_browser_polyfill = __commonJS({
41
42
  return false;
42
43
  }
43
44
  }(),
44
- formData: "FormData" in global,
45
- arrayBuffer: "ArrayBuffer" in global
45
+ formData: "FormData" in g,
46
+ arrayBuffer: "ArrayBuffer" in g
46
47
  };
47
48
  function isDataView(obj) {
48
49
  return obj && DataView.prototype.isPrototypeOf(obj);
@@ -100,6 +101,9 @@ var require_browser_polyfill = __commonJS({
100
101
  }, this);
101
102
  } else if (Array.isArray(headers)) {
102
103
  headers.forEach(function(header) {
104
+ if (header.length != 2) {
105
+ throw new TypeError("Headers constructor: expected name/value pair to be length 2, found" + header.length);
106
+ }
103
107
  this.append(header[0], header[1]);
104
108
  }, this);
105
109
  } else if (headers) {
@@ -159,6 +163,7 @@ var require_browser_polyfill = __commonJS({
159
163
  Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
160
164
  }
161
165
  function consumed(body) {
166
+ if (body._noBody) return;
162
167
  if (body.bodyUsed) {
163
168
  return Promise.reject(new TypeError("Already read"));
164
169
  }
@@ -183,7 +188,9 @@ var require_browser_polyfill = __commonJS({
183
188
  function readBlobAsText(blob) {
184
189
  var reader = new FileReader();
185
190
  var promise = fileReaderReady(reader);
186
- reader.readAsText(blob);
191
+ var match = /charset=([A-Za-z0-9_-]+)/.exec(blob.type);
192
+ var encoding = match ? match[1] : "utf-8";
193
+ reader.readAsText(blob, encoding);
187
194
  return promise;
188
195
  }
189
196
  function readArrayBufferAsText(buf) {
@@ -209,6 +216,7 @@ var require_browser_polyfill = __commonJS({
209
216
  this.bodyUsed = this.bodyUsed;
210
217
  this._bodyInit = body;
211
218
  if (!body) {
219
+ this._noBody = true;
212
220
  this._bodyText = "";
213
221
  } else if (typeof body === "string") {
214
222
  this._bodyText = body;
@@ -252,27 +260,28 @@ var require_browser_polyfill = __commonJS({
252
260
  return Promise.resolve(new Blob([this._bodyText]));
253
261
  }
254
262
  };
255
- this.arrayBuffer = function() {
256
- if (this._bodyArrayBuffer) {
257
- var isConsumed = consumed(this);
258
- if (isConsumed) {
259
- return isConsumed;
260
- }
261
- if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
262
- return Promise.resolve(
263
- this._bodyArrayBuffer.buffer.slice(
264
- this._bodyArrayBuffer.byteOffset,
265
- this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength
266
- )
267
- );
268
- } else {
269
- return Promise.resolve(this._bodyArrayBuffer);
270
- }
263
+ }
264
+ this.arrayBuffer = function() {
265
+ if (this._bodyArrayBuffer) {
266
+ var isConsumed = consumed(this);
267
+ if (isConsumed) {
268
+ return isConsumed;
269
+ } else if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
270
+ return Promise.resolve(
271
+ this._bodyArrayBuffer.buffer.slice(
272
+ this._bodyArrayBuffer.byteOffset,
273
+ this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength
274
+ )
275
+ );
271
276
  } else {
272
- return this.blob().then(readBlobAsArrayBuffer);
277
+ return Promise.resolve(this._bodyArrayBuffer);
273
278
  }
274
- };
275
- }
279
+ } else if (support.blob) {
280
+ return this.blob().then(readBlobAsArrayBuffer);
281
+ } else {
282
+ throw new Error("could not read as ArrayBuffer");
283
+ }
284
+ };
276
285
  this.text = function() {
277
286
  var rejected = consumed(this);
278
287
  if (rejected) {
@@ -298,7 +307,7 @@ var require_browser_polyfill = __commonJS({
298
307
  };
299
308
  return this;
300
309
  }
301
- var methods = ["DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT"];
310
+ var methods = ["CONNECT", "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT", "TRACE"];
302
311
  function normalizeMethod(method) {
303
312
  var upcased = method.toUpperCase();
304
313
  return methods.indexOf(upcased) > -1 ? upcased : method;
@@ -334,7 +343,12 @@ var require_browser_polyfill = __commonJS({
334
343
  }
335
344
  this.method = normalizeMethod(options.method || this.method || "GET");
336
345
  this.mode = options.mode || this.mode || null;
337
- this.signal = options.signal || this.signal;
346
+ this.signal = options.signal || this.signal || function() {
347
+ if ("AbortController" in g) {
348
+ var ctrl = new AbortController();
349
+ return ctrl.signal;
350
+ }
351
+ }();
338
352
  this.referrer = null;
339
353
  if ((this.method === "GET" || this.method === "HEAD") && body) {
340
354
  throw new TypeError("Body not allowed for GET or HEAD requests");
@@ -377,7 +391,11 @@ var require_browser_polyfill = __commonJS({
377
391
  var key = parts.shift().trim();
378
392
  if (key) {
379
393
  var value = parts.join(":").trim();
380
- headers.append(key, value);
394
+ try {
395
+ headers.append(key, value);
396
+ } catch (error) {
397
+ console.warn("Response " + error.message);
398
+ }
381
399
  }
382
400
  });
383
401
  return headers;
@@ -392,6 +410,9 @@ var require_browser_polyfill = __commonJS({
392
410
  }
393
411
  this.type = "default";
394
412
  this.status = options.status === void 0 ? 200 : options.status;
413
+ if (this.status < 200 || this.status > 599) {
414
+ throw new RangeError("Failed to construct 'Response': The status provided (0) is outside the range [200, 599].");
415
+ }
395
416
  this.ok = this.status >= 200 && this.status < 300;
396
417
  this.statusText = options.statusText === void 0 ? "" : "" + options.statusText;
397
418
  this.headers = new Headers(options.headers);
@@ -408,7 +429,9 @@ var require_browser_polyfill = __commonJS({
408
429
  });
409
430
  };
410
431
  Response.error = function() {
411
- var response = new Response(null, { status: 0, statusText: "" });
432
+ var response = new Response(null, { status: 200, statusText: "" });
433
+ response.ok = false;
434
+ response.status = 0;
412
435
  response.type = "error";
413
436
  return response;
414
437
  };
@@ -419,7 +442,7 @@ var require_browser_polyfill = __commonJS({
419
442
  }
420
443
  return new Response(null, { status, headers: { location: url } });
421
444
  };
422
- exports2.DOMException = global.DOMException;
445
+ exports2.DOMException = g.DOMException;
423
446
  try {
424
447
  new exports2.DOMException();
425
448
  } catch (err) {
@@ -444,10 +467,14 @@ var require_browser_polyfill = __commonJS({
444
467
  }
445
468
  xhr.onload = function() {
446
469
  var options = {
447
- status: xhr.status,
448
470
  statusText: xhr.statusText,
449
471
  headers: parseHeaders(xhr.getAllResponseHeaders() || "")
450
472
  };
473
+ if (request.url.indexOf("file://") === 0 && (xhr.status < 200 || xhr.status > 599)) {
474
+ options.status = 200;
475
+ } else {
476
+ options.status = xhr.status;
477
+ }
451
478
  options.url = "responseURL" in xhr ? xhr.responseURL : options.headers.get("X-Request-URL");
452
479
  var body = "response" in xhr ? xhr.response : xhr.responseText;
453
480
  setTimeout(function() {
@@ -461,7 +488,7 @@ var require_browser_polyfill = __commonJS({
461
488
  };
462
489
  xhr.ontimeout = function() {
463
490
  setTimeout(function() {
464
- reject(new TypeError("Network request failed"));
491
+ reject(new TypeError("Network request timed out"));
465
492
  }, 0);
466
493
  };
467
494
  xhr.onabort = function() {
@@ -471,7 +498,7 @@ var require_browser_polyfill = __commonJS({
471
498
  };
472
499
  function fixUrl(url) {
473
500
  try {
474
- return url === "" && global.location.href ? global.location.href : url;
501
+ return url === "" && g.location.href ? g.location.href : url;
475
502
  } catch (e) {
476
503
  return url;
477
504
  }
@@ -485,14 +512,21 @@ var require_browser_polyfill = __commonJS({
485
512
  if ("responseType" in xhr) {
486
513
  if (support.blob) {
487
514
  xhr.responseType = "blob";
488
- } else if (support.arrayBuffer && request.headers.get("Content-Type") && request.headers.get("Content-Type").indexOf("application/octet-stream") !== -1) {
515
+ } else if (support.arrayBuffer) {
489
516
  xhr.responseType = "arraybuffer";
490
517
  }
491
518
  }
492
- if (init && typeof init.headers === "object" && !(init.headers instanceof Headers)) {
519
+ if (init && typeof init.headers === "object" && !(init.headers instanceof Headers || g.Headers && init.headers instanceof g.Headers)) {
520
+ var names = [];
493
521
  Object.getOwnPropertyNames(init.headers).forEach(function(name) {
522
+ names.push(normalizeName(name));
494
523
  xhr.setRequestHeader(name, normalizeValue(init.headers[name]));
495
524
  });
525
+ request.headers.forEach(function(value, name) {
526
+ if (names.indexOf(name) === -1) {
527
+ xhr.setRequestHeader(name, value);
528
+ }
529
+ });
496
530
  } else {
497
531
  request.headers.forEach(function(value, name) {
498
532
  xhr.setRequestHeader(name, value);
@@ -510,11 +544,11 @@ var require_browser_polyfill = __commonJS({
510
544
  });
511
545
  }
512
546
  fetch2.polyfill = true;
513
- if (!global.fetch) {
514
- global.fetch = fetch2;
515
- global.Headers = Headers;
516
- global.Request = Request;
517
- global.Response = Response;
547
+ if (!g.fetch) {
548
+ g.fetch = fetch2;
549
+ g.Headers = Headers;
550
+ g.Request = Request;
551
+ g.Response = Response;
518
552
  }
519
553
  exports2.Headers = Headers;
520
554
  exports2.Request = Request;
@@ -528,10 +562,9 @@ var require_browser_polyfill = __commonJS({
528
562
 
529
563
  // node_modules/uuid/dist/esm-browser/stringify.js
530
564
  var byteToHex = [];
531
- for (i = 0; i < 256; ++i) {
565
+ for (let i = 0; i < 256; ++i) {
532
566
  byteToHex.push((i + 256).toString(16).slice(1));
533
567
  }
534
- var i;
535
568
  function unsafeStringify(arr, offset = 0) {
536
569
  return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
537
570
  }
@@ -541,19 +574,17 @@ var getRandomValues;
541
574
  var rnds8 = new Uint8Array(16);
542
575
  function rng() {
543
576
  if (!getRandomValues) {
544
- getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
545
- if (!getRandomValues) {
577
+ if (typeof crypto === "undefined" || !crypto.getRandomValues) {
546
578
  throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
547
579
  }
580
+ getRandomValues = crypto.getRandomValues.bind(crypto);
548
581
  }
549
582
  return getRandomValues(rnds8);
550
583
  }
551
584
 
552
585
  // node_modules/uuid/dist/esm-browser/native.js
553
586
  var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
554
- var native_default = {
555
- randomUUID
556
- };
587
+ var native_default = { randomUUID };
557
588
 
558
589
  // node_modules/uuid/dist/esm-browser/v4.js
559
590
  function v4(options, buf, offset) {
@@ -561,12 +592,18 @@ function v4(options, buf, offset) {
561
592
  return native_default.randomUUID();
562
593
  }
563
594
  options = options || {};
564
- var rnds = options.random || (options.rng || rng)();
595
+ const rnds = options.random ?? options.rng?.() ?? rng();
596
+ if (rnds.length < 16) {
597
+ throw new Error("Random bytes length must be >= 16");
598
+ }
565
599
  rnds[6] = rnds[6] & 15 | 64;
566
600
  rnds[8] = rnds[8] & 63 | 128;
567
601
  if (buf) {
568
602
  offset = offset || 0;
569
- for (var i = 0; i < 16; ++i) {
603
+ if (offset < 0 || offset + 16 > buf.length) {
604
+ throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
605
+ }
606
+ for (let i = 0; i < 16; ++i) {
570
607
  buf[offset + i] = rnds[i];
571
608
  }
572
609
  return buf;
@@ -578,6 +615,127 @@ var v4_default = v4;
578
615
  // src/index.ts
579
616
  var import_polyfill = __toESM(require_browser_polyfill());
580
617
 
618
+ // src/types/api/models/CheckFlagResponseData.ts
619
+ function CheckFlagResponseDataFromJSON(json) {
620
+ return CheckFlagResponseDataFromJSONTyped(json, false);
621
+ }
622
+ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
623
+ if (json == null) {
624
+ return json;
625
+ }
626
+ return {
627
+ companyId: json["company_id"] == null ? void 0 : json["company_id"],
628
+ error: json["error"] == null ? void 0 : json["error"],
629
+ featureAllocation: json["feature_allocation"] == null ? void 0 : json["feature_allocation"],
630
+ featureUsage: json["feature_usage"] == null ? void 0 : json["feature_usage"],
631
+ featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : json["feature_usage_period"],
632
+ featureUsageResetAt: json["feature_usage_reset_at"] == null ? void 0 : new Date(json["feature_usage_reset_at"]),
633
+ flag: json["flag"],
634
+ flagId: json["flag_id"] == null ? void 0 : json["flag_id"],
635
+ reason: json["reason"],
636
+ ruleId: json["rule_id"] == null ? void 0 : json["rule_id"],
637
+ ruleType: json["rule_type"] == null ? void 0 : json["rule_type"],
638
+ userId: json["user_id"] == null ? void 0 : json["user_id"],
639
+ value: json["value"]
640
+ };
641
+ }
642
+
643
+ // src/types/api/models/CheckFlagResponse.ts
644
+ function CheckFlagResponseFromJSON(json) {
645
+ return CheckFlagResponseFromJSONTyped(json, false);
646
+ }
647
+ function CheckFlagResponseFromJSONTyped(json, ignoreDiscriminator) {
648
+ if (json == null) {
649
+ return json;
650
+ }
651
+ return {
652
+ data: CheckFlagResponseDataFromJSON(json["data"]),
653
+ params: json["params"]
654
+ };
655
+ }
656
+
657
+ // src/types/api/models/CheckFlagsResponseData.ts
658
+ function CheckFlagsResponseDataFromJSON(json) {
659
+ return CheckFlagsResponseDataFromJSONTyped(json, false);
660
+ }
661
+ function CheckFlagsResponseDataFromJSONTyped(json, ignoreDiscriminator) {
662
+ if (json == null) {
663
+ return json;
664
+ }
665
+ return {
666
+ flags: json["flags"].map(CheckFlagResponseDataFromJSON)
667
+ };
668
+ }
669
+
670
+ // src/types/api/models/CheckFlagsResponse.ts
671
+ function CheckFlagsResponseFromJSON(json) {
672
+ return CheckFlagsResponseFromJSONTyped(json, false);
673
+ }
674
+ function CheckFlagsResponseFromJSONTyped(json, ignoreDiscriminator) {
675
+ if (json == null) {
676
+ return json;
677
+ }
678
+ return {
679
+ data: CheckFlagsResponseDataFromJSON(json["data"]),
680
+ params: json["params"]
681
+ };
682
+ }
683
+
684
+ // src/types/index.ts
685
+ var RuleType = /* @__PURE__ */ ((RuleType2) => {
686
+ RuleType2["GLOBAL_OVERRIDE"] = "global_override";
687
+ RuleType2["COMPANY_OVERRIDE"] = "company_override";
688
+ RuleType2["COMPANY_OVERRIDE_USAGE_EXCEEDED"] = "company_override_usage_exceeded";
689
+ RuleType2["PLAN_ENTITLEMENT"] = "plan_entitlement";
690
+ RuleType2["PLAN_ENTITLEMENT_USAGE_EXCEEDED"] = "plan_entitlement_usage_exceeded";
691
+ RuleType2["STANDARD"] = "standard";
692
+ RuleType2["DEFAULT"] = "default";
693
+ return RuleType2;
694
+ })(RuleType || {});
695
+ var UsagePeriod = /* @__PURE__ */ ((UsagePeriod2) => {
696
+ UsagePeriod2["ALL_TIME"] = "all_time";
697
+ UsagePeriod2["CURRENT_DAY"] = "current_day";
698
+ UsagePeriod2["CURRENT_MONTH"] = "current_month";
699
+ UsagePeriod2["CURRENT_WEEK"] = "current_week";
700
+ return UsagePeriod2;
701
+ })(UsagePeriod || {});
702
+ var CheckFlagReturnFromJSON = (json) => {
703
+ const {
704
+ companyId,
705
+ error,
706
+ featureAllocation,
707
+ featureUsage,
708
+ featureUsagePeriod,
709
+ featureUsageResetAt,
710
+ flag,
711
+ flagId,
712
+ reason,
713
+ ruleId,
714
+ ruleType,
715
+ userId,
716
+ value
717
+ } = CheckFlagResponseDataFromJSON(json);
718
+ const featureUsageExceeded = !value && // if flag is not false, then we haven't exceeded usage
719
+ (ruleType == "company_override_usage_exceeded" /* COMPANY_OVERRIDE_USAGE_EXCEEDED */ || // if the rule type is one of these, then we have exceeded usage
720
+ ruleType == "plan_entitlement_usage_exceeded" /* PLAN_ENTITLEMENT_USAGE_EXCEEDED */);
721
+ return {
722
+ featureUsageExceeded,
723
+ companyId: companyId == null ? void 0 : companyId,
724
+ error: error == null ? void 0 : error,
725
+ featureAllocation: featureAllocation == null ? void 0 : featureAllocation,
726
+ featureUsage: featureUsage == null ? void 0 : featureUsage,
727
+ featureUsagePeriod: featureUsagePeriod == null ? void 0 : featureUsagePeriod,
728
+ featureUsageResetAt: featureUsageResetAt == null ? void 0 : featureUsageResetAt,
729
+ flag,
730
+ flagId: flagId == null ? void 0 : flagId,
731
+ reason,
732
+ ruleId: ruleId == null ? void 0 : ruleId,
733
+ ruleType: ruleType == null ? void 0 : ruleType,
734
+ userId: userId == null ? void 0 : userId,
735
+ value
736
+ };
737
+ };
738
+
581
739
  // src/utils.ts
582
740
  function contextString(context) {
583
741
  const sortedContext = Object.keys(context).reduce((acc, key) => {
@@ -604,19 +762,18 @@ var Schematic = class {
604
762
  context = {};
605
763
  eventQueue;
606
764
  eventUrl = "https://c.schematichq.com";
607
- flagListener;
765
+ flagCheckListeners = {};
608
766
  flagValueListeners = {};
609
767
  isPending = true;
610
768
  isPendingListeners = /* @__PURE__ */ new Set();
611
769
  storage;
612
770
  useWebSocket = false;
613
- values = {};
771
+ checks = {};
614
772
  webSocketUrl = "wss://api.schematichq.com";
615
773
  constructor(apiKey, options) {
616
774
  this.apiKey = apiKey;
617
775
  this.eventQueue = [];
618
776
  this.useWebSocket = options?.useWebSocket ?? false;
619
- this.flagListener = options?.flagListener;
620
777
  if (options?.additionalHeaders) {
621
778
  this.additionalHeaders = options.additionalHeaders;
622
779
  }
@@ -666,17 +823,17 @@ var Schematic = class {
666
823
  throw new Error("Network response was not ok");
667
824
  }
668
825
  return response.json();
669
- }).then((data) => {
670
- return data.data.value;
826
+ }).then((response) => {
827
+ return CheckFlagResponseFromJSON(response).data.value;
671
828
  }).catch((error) => {
672
829
  console.error("There was a problem with the fetch operation:", error);
673
830
  return fallback;
674
831
  });
675
832
  }
676
833
  try {
677
- const existingVals = this.values[contextStr];
834
+ const existingVals = this.checks[contextStr];
678
835
  if (this.conn && typeof existingVals !== "undefined" && typeof existingVals[key] !== "undefined") {
679
- return existingVals[key];
836
+ return existingVals[key].value;
680
837
  }
681
838
  try {
682
839
  await this.setContext(context);
@@ -687,8 +844,8 @@ var Schematic = class {
687
844
  );
688
845
  return this.fallbackToRest(key, context, fallback);
689
846
  }
690
- const contextVals = this.values[contextStr] ?? {};
691
- return typeof contextVals[key] === "undefined" ? fallback : contextVals[key];
847
+ const contextVals = this.checks[contextStr] ?? {};
848
+ return contextVals[key]?.value ?? fallback;
692
849
  } catch (error) {
693
850
  console.error("Unexpected error in checkFlag:", error);
694
851
  return fallback;
@@ -712,8 +869,8 @@ var Schematic = class {
712
869
  if (!response.ok) {
713
870
  throw new Error("Network response was not ok");
714
871
  }
715
- const data = await response.json();
716
- return data.data.value;
872
+ const data = CheckFlagResponseFromJSON(await response.json());
873
+ return data?.data?.value ?? false;
717
874
  } catch (error) {
718
875
  console.error("REST API call failed, using fallback value:", error);
719
876
  return fallback;
@@ -740,8 +897,9 @@ var Schematic = class {
740
897
  throw new Error("Network response was not ok");
741
898
  }
742
899
  return response.json();
743
- }).then((data) => {
744
- return (data?.data?.flags ?? []).reduce(
900
+ }).then((responseJson) => {
901
+ const resp = CheckFlagsResponseFromJSON(responseJson);
902
+ return (resp?.data?.flags ?? []).reduce(
745
903
  (accum, flag) => {
746
904
  accum[flag.flag] = flag.value;
747
905
  return accum;
@@ -750,7 +908,7 @@ var Schematic = class {
750
908
  );
751
909
  }).catch((error) => {
752
910
  console.error("There was a problem with the fetch operation:", error);
753
- return false;
911
+ return {};
754
912
  });
755
913
  };
756
914
  /**
@@ -912,18 +1070,15 @@ var Schematic = class {
912
1070
  let resolved = false;
913
1071
  const messageHandler = (event) => {
914
1072
  const message = JSON.parse(event.data);
915
- if (!(contextString(context) in this.values)) {
916
- this.values[contextString(context)] = {};
917
- }
918
- (message.flags ?? []).forEach(
919
- (flag) => {
920
- this.values[contextString(context)][flag.flag] = flag.value;
921
- this.notifyFlagValueListeners(flag.flag, flag.value);
922
- }
923
- );
924
- if (this.flagListener) {
925
- this.flagListener(this.getFlagValues());
1073
+ if (!(contextString(context) in this.checks)) {
1074
+ this.checks[contextString(context)] = {};
926
1075
  }
1076
+ (message.flags ?? []).forEach((flag) => {
1077
+ const flagCheck = CheckFlagReturnFromJSON(flag);
1078
+ this.checks[contextString(context)][flagCheck.flag] = flagCheck;
1079
+ this.notifyFlagCheckListeners(flag.flag, flagCheck);
1080
+ this.notifyFlagValueListeners(flag.flag, flagCheck.value);
1081
+ });
927
1082
  this.setIsPending(false);
928
1083
  if (!resolved) {
929
1084
  resolved = true;
@@ -963,18 +1118,21 @@ var Schematic = class {
963
1118
  setIsPending = (isPending) => {
964
1119
  this.isPending = isPending;
965
1120
  this.isPendingListeners.forEach(
966
- (listener) => notifyListener(listener, isPending)
1121
+ (listener) => notifyPendingListener(listener, isPending)
967
1122
  );
968
1123
  };
1124
+ // flag checks state
1125
+ getFlagCheck = (flagKey) => {
1126
+ const contextStr = contextString(this.context);
1127
+ const checks = this.checks[contextStr] ?? {};
1128
+ return checks[flagKey];
1129
+ };
969
1130
  // flagValues state
970
1131
  getFlagValue = (flagKey) => {
971
- const values = this.getFlagValues();
972
- return values[flagKey];
973
- };
974
- getFlagValues = () => {
975
- const contextStr = contextString(this.context);
976
- return this.values[contextStr] ?? {};
1132
+ const check = this.getFlagCheck(flagKey);
1133
+ return check?.value;
977
1134
  };
1135
+ /** Register an event listener that will be notified with the boolean value for a given flag when this value changes */
978
1136
  addFlagValueListener = (flagKey, listener) => {
979
1137
  if (!(flagKey in this.flagValueListeners)) {
980
1138
  this.flagValueListeners[flagKey] = /* @__PURE__ */ new Set();
@@ -984,12 +1142,40 @@ var Schematic = class {
984
1142
  this.flagValueListeners[flagKey].delete(listener);
985
1143
  };
986
1144
  };
1145
+ /** Register an event listener that will be notified with the full flag check response for a given flag whenever this value changes */
1146
+ addFlagCheckListener = (flagKey, listener) => {
1147
+ if (!(flagKey in this.flagCheckListeners)) {
1148
+ this.flagCheckListeners[flagKey] = /* @__PURE__ */ new Set();
1149
+ }
1150
+ this.flagCheckListeners[flagKey].add(listener);
1151
+ return () => {
1152
+ this.flagCheckListeners[flagKey].delete(listener);
1153
+ };
1154
+ };
1155
+ notifyFlagCheckListeners = (flagKey, check) => {
1156
+ const listeners = this.flagCheckListeners?.[flagKey] ?? [];
1157
+ listeners.forEach((listener) => notifyFlagCheckListener(listener, check));
1158
+ };
987
1159
  notifyFlagValueListeners = (flagKey, value) => {
988
1160
  const listeners = this.flagValueListeners?.[flagKey] ?? [];
989
- listeners.forEach((listener) => notifyListener(listener, value));
1161
+ listeners.forEach((listener) => notifyFlagValueListener(listener, value));
990
1162
  };
991
1163
  };
992
- var notifyListener = (listener, value) => {
1164
+ var notifyPendingListener = (listener, value) => {
1165
+ if (listener.length > 0) {
1166
+ listener(value);
1167
+ } else {
1168
+ listener();
1169
+ }
1170
+ };
1171
+ var notifyFlagCheckListener = (listener, value) => {
1172
+ if (listener.length > 0) {
1173
+ listener(value);
1174
+ } else {
1175
+ listener();
1176
+ }
1177
+ };
1178
+ var notifyFlagValueListener = (listener, value) => {
993
1179
  if (listener.length > 0) {
994
1180
  listener(value);
995
1181
  } else {
@@ -997,6 +1183,11 @@ var notifyListener = (listener, value) => {
997
1183
  }
998
1184
  };
999
1185
  export {
1000
- Schematic
1186
+ CheckFlagResponseFromJSON,
1187
+ CheckFlagReturnFromJSON,
1188
+ CheckFlagsResponseFromJSON,
1189
+ RuleType,
1190
+ Schematic,
1191
+ UsagePeriod
1001
1192
  };
1002
1193
  /* @preserve */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schematichq/schematic-js",
3
- "version": "1.0.3",
3
+ "version": "1.1.0",
4
4
  "main": "dist/schematic.cjs.js",
5
5
  "module": "dist/schematic.esm.js",
6
6
  "types": "dist/schematic.d.ts",
@@ -25,14 +25,16 @@
25
25
  "clean": "rm -rf dist",
26
26
  "format": "prettier --write src/*.ts",
27
27
  "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --fix",
28
+ "openapi": "rm -rf src/types/api/ && npx openapi-generator-cli generate -c openapi-config.yaml --global-property models=\"EventBody:EventBodyFlagCheck:EventBodyIdentify:EventBodyIdentifyCompany:EventBodyTrack:CheckFlagResponse:CheckFlagResponseData:CheckFlagsResponse:CheckFlagsResponseData\",supportingFiles=runtime.ts && prettier --write \"src/types/api/**/*.{ts,tsx}\"",
28
29
  "test": "jest --config jest.config.js"
29
30
  },
30
31
  "dependencies": {
31
32
  "cross-fetch": "^4.0.0",
32
- "uuid": "^10.0.0"
33
+ "uuid": "^11.0.1"
33
34
  },
34
35
  "devDependencies": {
35
36
  "@microsoft/api-extractor": "^7.47.9",
37
+ "@openapitools/openapi-generator-cli": "^2.15.3",
36
38
  "@types/jest": "^29.5.13",
37
39
  "@types/uuid": "^10.0.0",
38
40
  "@typescript-eslint/eslint-plugin": "^8.7.0",