@schematichq/schematic-react 1.0.3 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -28,11 +28,12 @@ var require_browser_polyfill = __commonJS({
28
28
  "node_modules/cross-fetch/dist/browser-polyfill.js"(exports) {
29
29
  (function(self2) {
30
30
  var irrelevant = function(exports2) {
31
- var global = typeof globalThis !== "undefined" && globalThis || typeof self2 !== "undefined" && self2 || typeof global !== "undefined" && global;
31
+ var g = typeof globalThis !== "undefined" && globalThis || typeof self2 !== "undefined" && self2 || // eslint-disable-next-line no-undef
32
+ typeof global !== "undefined" && global || {};
32
33
  var support = {
33
- searchParams: "URLSearchParams" in global,
34
- iterable: "Symbol" in global && "iterator" in Symbol,
35
- blob: "FileReader" in global && "Blob" in global && function() {
34
+ searchParams: "URLSearchParams" in g,
35
+ iterable: "Symbol" in g && "iterator" in Symbol,
36
+ blob: "FileReader" in g && "Blob" in g && function() {
36
37
  try {
37
38
  new Blob();
38
39
  return true;
@@ -40,8 +41,8 @@ var require_browser_polyfill = __commonJS({
40
41
  return false;
41
42
  }
42
43
  }(),
43
- formData: "FormData" in global,
44
- arrayBuffer: "ArrayBuffer" in global
44
+ formData: "FormData" in g,
45
+ arrayBuffer: "ArrayBuffer" in g
45
46
  };
46
47
  function isDataView(obj) {
47
48
  return obj && DataView.prototype.isPrototypeOf(obj);
@@ -99,6 +100,9 @@ var require_browser_polyfill = __commonJS({
99
100
  }, this);
100
101
  } else if (Array.isArray(headers)) {
101
102
  headers.forEach(function(header) {
103
+ if (header.length != 2) {
104
+ throw new TypeError("Headers constructor: expected name/value pair to be length 2, found" + header.length);
105
+ }
102
106
  this.append(header[0], header[1]);
103
107
  }, this);
104
108
  } else if (headers) {
@@ -158,6 +162,7 @@ var require_browser_polyfill = __commonJS({
158
162
  Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
159
163
  }
160
164
  function consumed(body) {
165
+ if (body._noBody) return;
161
166
  if (body.bodyUsed) {
162
167
  return Promise.reject(new TypeError("Already read"));
163
168
  }
@@ -182,14 +187,16 @@ var require_browser_polyfill = __commonJS({
182
187
  function readBlobAsText(blob) {
183
188
  var reader = new FileReader();
184
189
  var promise = fileReaderReady(reader);
185
- reader.readAsText(blob);
190
+ var match = /charset=([A-Za-z0-9_-]+)/.exec(blob.type);
191
+ var encoding = match ? match[1] : "utf-8";
192
+ reader.readAsText(blob, encoding);
186
193
  return promise;
187
194
  }
188
195
  function readArrayBufferAsText(buf) {
189
196
  var view = new Uint8Array(buf);
190
197
  var chars = new Array(view.length);
191
- for (var i2 = 0; i2 < view.length; i2++) {
192
- chars[i2] = String.fromCharCode(view[i2]);
198
+ for (var i = 0; i < view.length; i++) {
199
+ chars[i] = String.fromCharCode(view[i]);
193
200
  }
194
201
  return chars.join("");
195
202
  }
@@ -208,6 +215,7 @@ var require_browser_polyfill = __commonJS({
208
215
  this.bodyUsed = this.bodyUsed;
209
216
  this._bodyInit = body;
210
217
  if (!body) {
218
+ this._noBody = true;
211
219
  this._bodyText = "";
212
220
  } else if (typeof body === "string") {
213
221
  this._bodyText = body;
@@ -251,27 +259,28 @@ var require_browser_polyfill = __commonJS({
251
259
  return Promise.resolve(new Blob([this._bodyText]));
252
260
  }
253
261
  };
254
- this.arrayBuffer = function() {
255
- if (this._bodyArrayBuffer) {
256
- var isConsumed = consumed(this);
257
- if (isConsumed) {
258
- return isConsumed;
259
- }
260
- if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
261
- return Promise.resolve(
262
- this._bodyArrayBuffer.buffer.slice(
263
- this._bodyArrayBuffer.byteOffset,
264
- this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength
265
- )
266
- );
267
- } else {
268
- return Promise.resolve(this._bodyArrayBuffer);
269
- }
262
+ }
263
+ this.arrayBuffer = function() {
264
+ if (this._bodyArrayBuffer) {
265
+ var isConsumed = consumed(this);
266
+ if (isConsumed) {
267
+ return isConsumed;
268
+ } else if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
269
+ return Promise.resolve(
270
+ this._bodyArrayBuffer.buffer.slice(
271
+ this._bodyArrayBuffer.byteOffset,
272
+ this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength
273
+ )
274
+ );
270
275
  } else {
271
- return this.blob().then(readBlobAsArrayBuffer);
276
+ return Promise.resolve(this._bodyArrayBuffer);
272
277
  }
273
- };
274
- }
278
+ } else if (support.blob) {
279
+ return this.blob().then(readBlobAsArrayBuffer);
280
+ } else {
281
+ throw new Error("could not read as ArrayBuffer");
282
+ }
283
+ };
275
284
  this.text = function() {
276
285
  var rejected = consumed(this);
277
286
  if (rejected) {
@@ -297,7 +306,7 @@ var require_browser_polyfill = __commonJS({
297
306
  };
298
307
  return this;
299
308
  }
300
- var methods = ["DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT"];
309
+ var methods = ["CONNECT", "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT", "TRACE"];
301
310
  function normalizeMethod(method) {
302
311
  var upcased = method.toUpperCase();
303
312
  return methods.indexOf(upcased) > -1 ? upcased : method;
@@ -333,7 +342,12 @@ var require_browser_polyfill = __commonJS({
333
342
  }
334
343
  this.method = normalizeMethod(options.method || this.method || "GET");
335
344
  this.mode = options.mode || this.mode || null;
336
- this.signal = options.signal || this.signal;
345
+ this.signal = options.signal || this.signal || function() {
346
+ if ("AbortController" in g) {
347
+ var ctrl = new AbortController();
348
+ return ctrl.signal;
349
+ }
350
+ }();
337
351
  this.referrer = null;
338
352
  if ((this.method === "GET" || this.method === "HEAD") && body) {
339
353
  throw new TypeError("Body not allowed for GET or HEAD requests");
@@ -376,7 +390,11 @@ var require_browser_polyfill = __commonJS({
376
390
  var key = parts.shift().trim();
377
391
  if (key) {
378
392
  var value = parts.join(":").trim();
379
- headers.append(key, value);
393
+ try {
394
+ headers.append(key, value);
395
+ } catch (error) {
396
+ console.warn("Response " + error.message);
397
+ }
380
398
  }
381
399
  });
382
400
  return headers;
@@ -391,6 +409,9 @@ var require_browser_polyfill = __commonJS({
391
409
  }
392
410
  this.type = "default";
393
411
  this.status = options.status === void 0 ? 200 : options.status;
412
+ if (this.status < 200 || this.status > 599) {
413
+ throw new RangeError("Failed to construct 'Response': The status provided (0) is outside the range [200, 599].");
414
+ }
394
415
  this.ok = this.status >= 200 && this.status < 300;
395
416
  this.statusText = options.statusText === void 0 ? "" : "" + options.statusText;
396
417
  this.headers = new Headers(options.headers);
@@ -407,7 +428,9 @@ var require_browser_polyfill = __commonJS({
407
428
  });
408
429
  };
409
430
  Response.error = function() {
410
- var response = new Response(null, { status: 0, statusText: "" });
431
+ var response = new Response(null, { status: 200, statusText: "" });
432
+ response.ok = false;
433
+ response.status = 0;
411
434
  response.type = "error";
412
435
  return response;
413
436
  };
@@ -418,7 +441,7 @@ var require_browser_polyfill = __commonJS({
418
441
  }
419
442
  return new Response(null, { status, headers: { location: url } });
420
443
  };
421
- exports2.DOMException = global.DOMException;
444
+ exports2.DOMException = g.DOMException;
422
445
  try {
423
446
  new exports2.DOMException();
424
447
  } catch (err) {
@@ -443,10 +466,14 @@ var require_browser_polyfill = __commonJS({
443
466
  }
444
467
  xhr.onload = function() {
445
468
  var options = {
446
- status: xhr.status,
447
469
  statusText: xhr.statusText,
448
470
  headers: parseHeaders(xhr.getAllResponseHeaders() || "")
449
471
  };
472
+ if (request.url.indexOf("file://") === 0 && (xhr.status < 200 || xhr.status > 599)) {
473
+ options.status = 200;
474
+ } else {
475
+ options.status = xhr.status;
476
+ }
450
477
  options.url = "responseURL" in xhr ? xhr.responseURL : options.headers.get("X-Request-URL");
451
478
  var body = "response" in xhr ? xhr.response : xhr.responseText;
452
479
  setTimeout(function() {
@@ -460,7 +487,7 @@ var require_browser_polyfill = __commonJS({
460
487
  };
461
488
  xhr.ontimeout = function() {
462
489
  setTimeout(function() {
463
- reject(new TypeError("Network request failed"));
490
+ reject(new TypeError("Network request timed out"));
464
491
  }, 0);
465
492
  };
466
493
  xhr.onabort = function() {
@@ -470,7 +497,7 @@ var require_browser_polyfill = __commonJS({
470
497
  };
471
498
  function fixUrl(url) {
472
499
  try {
473
- return url === "" && global.location.href ? global.location.href : url;
500
+ return url === "" && g.location.href ? g.location.href : url;
474
501
  } catch (e) {
475
502
  return url;
476
503
  }
@@ -484,14 +511,21 @@ var require_browser_polyfill = __commonJS({
484
511
  if ("responseType" in xhr) {
485
512
  if (support.blob) {
486
513
  xhr.responseType = "blob";
487
- } else if (support.arrayBuffer && request.headers.get("Content-Type") && request.headers.get("Content-Type").indexOf("application/octet-stream") !== -1) {
514
+ } else if (support.arrayBuffer) {
488
515
  xhr.responseType = "arraybuffer";
489
516
  }
490
517
  }
491
- if (init && typeof init.headers === "object" && !(init.headers instanceof Headers)) {
518
+ if (init && typeof init.headers === "object" && !(init.headers instanceof Headers || g.Headers && init.headers instanceof g.Headers)) {
519
+ var names = [];
492
520
  Object.getOwnPropertyNames(init.headers).forEach(function(name) {
521
+ names.push(normalizeName(name));
493
522
  xhr.setRequestHeader(name, normalizeValue(init.headers[name]));
494
523
  });
524
+ request.headers.forEach(function(value, name) {
525
+ if (names.indexOf(name) === -1) {
526
+ xhr.setRequestHeader(name, value);
527
+ }
528
+ });
495
529
  } else {
496
530
  request.headers.forEach(function(value, name) {
497
531
  xhr.setRequestHeader(name, value);
@@ -509,11 +543,11 @@ var require_browser_polyfill = __commonJS({
509
543
  });
510
544
  }
511
545
  fetch2.polyfill = true;
512
- if (!global.fetch) {
513
- global.fetch = fetch2;
514
- global.Headers = Headers;
515
- global.Request = Request;
516
- global.Response = Response;
546
+ if (!g.fetch) {
547
+ g.fetch = fetch2;
548
+ g.Headers = Headers;
549
+ g.Request = Request;
550
+ g.Response = Response;
517
551
  }
518
552
  exports2.Headers = Headers;
519
553
  exports2.Request = Request;
@@ -525,10 +559,9 @@ var require_browser_polyfill = __commonJS({
525
559
  }
526
560
  });
527
561
  var byteToHex = [];
528
- for (i = 0; i < 256; ++i) {
562
+ for (let i = 0; i < 256; ++i) {
529
563
  byteToHex.push((i + 256).toString(16).slice(1));
530
564
  }
531
- var i;
532
565
  function unsafeStringify(arr, offset = 0) {
533
566
  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();
534
567
  }
@@ -536,29 +569,33 @@ var getRandomValues;
536
569
  var rnds8 = new Uint8Array(16);
537
570
  function rng() {
538
571
  if (!getRandomValues) {
539
- getRandomValues = typeof crypto !== "undefined" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);
540
- if (!getRandomValues) {
572
+ if (typeof crypto === "undefined" || !crypto.getRandomValues) {
541
573
  throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
542
574
  }
575
+ getRandomValues = crypto.getRandomValues.bind(crypto);
543
576
  }
544
577
  return getRandomValues(rnds8);
545
578
  }
546
579
  var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
547
- var native_default = {
548
- randomUUID
549
- };
580
+ var native_default = { randomUUID };
550
581
  function v4(options, buf, offset) {
551
582
  if (native_default.randomUUID && !buf && !options) {
552
583
  return native_default.randomUUID();
553
584
  }
554
585
  options = options || {};
555
- var rnds = options.random || (options.rng || rng)();
586
+ const rnds = options.random ?? options.rng?.() ?? rng();
587
+ if (rnds.length < 16) {
588
+ throw new Error("Random bytes length must be >= 16");
589
+ }
556
590
  rnds[6] = rnds[6] & 15 | 64;
557
591
  rnds[8] = rnds[8] & 63 | 128;
558
592
  if (buf) {
559
593
  offset = offset || 0;
560
- for (var i2 = 0; i2 < 16; ++i2) {
561
- buf[offset + i2] = rnds[i2];
594
+ if (offset < 0 || offset + 16 > buf.length) {
595
+ throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
596
+ }
597
+ for (let i = 0; i < 16; ++i) {
598
+ buf[offset + i] = rnds[i];
562
599
  }
563
600
  return buf;
564
601
  }
@@ -566,6 +603,117 @@ function v4(options, buf, offset) {
566
603
  }
567
604
  var v4_default = v4;
568
605
  var import_polyfill = __toESM(require_browser_polyfill());
606
+ function CheckFlagResponseDataFromJSON(json) {
607
+ return CheckFlagResponseDataFromJSONTyped(json, false);
608
+ }
609
+ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
610
+ if (json == null) {
611
+ return json;
612
+ }
613
+ return {
614
+ companyId: json["company_id"] == null ? void 0 : json["company_id"],
615
+ error: json["error"] == null ? void 0 : json["error"],
616
+ featureAllocation: json["feature_allocation"] == null ? void 0 : json["feature_allocation"],
617
+ featureUsage: json["feature_usage"] == null ? void 0 : json["feature_usage"],
618
+ featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : json["feature_usage_period"],
619
+ featureUsageResetAt: json["feature_usage_reset_at"] == null ? void 0 : new Date(json["feature_usage_reset_at"]),
620
+ flag: json["flag"],
621
+ flagId: json["flag_id"] == null ? void 0 : json["flag_id"],
622
+ reason: json["reason"],
623
+ ruleId: json["rule_id"] == null ? void 0 : json["rule_id"],
624
+ ruleType: json["rule_type"] == null ? void 0 : json["rule_type"],
625
+ userId: json["user_id"] == null ? void 0 : json["user_id"],
626
+ value: json["value"]
627
+ };
628
+ }
629
+ function CheckFlagResponseFromJSON(json) {
630
+ return CheckFlagResponseFromJSONTyped(json, false);
631
+ }
632
+ function CheckFlagResponseFromJSONTyped(json, ignoreDiscriminator) {
633
+ if (json == null) {
634
+ return json;
635
+ }
636
+ return {
637
+ data: CheckFlagResponseDataFromJSON(json["data"]),
638
+ params: json["params"]
639
+ };
640
+ }
641
+ function CheckFlagsResponseDataFromJSON(json) {
642
+ return CheckFlagsResponseDataFromJSONTyped(json, false);
643
+ }
644
+ function CheckFlagsResponseDataFromJSONTyped(json, ignoreDiscriminator) {
645
+ if (json == null) {
646
+ return json;
647
+ }
648
+ return {
649
+ flags: json["flags"].map(CheckFlagResponseDataFromJSON)
650
+ };
651
+ }
652
+ function CheckFlagsResponseFromJSON(json) {
653
+ return CheckFlagsResponseFromJSONTyped(json, false);
654
+ }
655
+ function CheckFlagsResponseFromJSONTyped(json, ignoreDiscriminator) {
656
+ if (json == null) {
657
+ return json;
658
+ }
659
+ return {
660
+ data: CheckFlagsResponseDataFromJSON(json["data"]),
661
+ params: json["params"]
662
+ };
663
+ }
664
+ var RuleType = /* @__PURE__ */ ((RuleType2) => {
665
+ RuleType2["GLOBAL_OVERRIDE"] = "global_override";
666
+ RuleType2["COMPANY_OVERRIDE"] = "company_override";
667
+ RuleType2["COMPANY_OVERRIDE_USAGE_EXCEEDED"] = "company_override_usage_exceeded";
668
+ RuleType2["PLAN_ENTITLEMENT"] = "plan_entitlement";
669
+ RuleType2["PLAN_ENTITLEMENT_USAGE_EXCEEDED"] = "plan_entitlement_usage_exceeded";
670
+ RuleType2["STANDARD"] = "standard";
671
+ RuleType2["DEFAULT"] = "default";
672
+ return RuleType2;
673
+ })(RuleType || {});
674
+ var UsagePeriod = /* @__PURE__ */ ((UsagePeriod2) => {
675
+ UsagePeriod2["ALL_TIME"] = "all_time";
676
+ UsagePeriod2["CURRENT_DAY"] = "current_day";
677
+ UsagePeriod2["CURRENT_MONTH"] = "current_month";
678
+ UsagePeriod2["CURRENT_WEEK"] = "current_week";
679
+ return UsagePeriod2;
680
+ })(UsagePeriod || {});
681
+ var CheckFlagReturnFromJSON = (json) => {
682
+ const {
683
+ companyId,
684
+ error,
685
+ featureAllocation,
686
+ featureUsage,
687
+ featureUsagePeriod,
688
+ featureUsageResetAt,
689
+ flag,
690
+ flagId,
691
+ reason,
692
+ ruleId,
693
+ ruleType,
694
+ userId,
695
+ value
696
+ } = CheckFlagResponseDataFromJSON(json);
697
+ const featureUsageExceeded = !value && // if flag is not false, then we haven't exceeded usage
698
+ (ruleType == "company_override_usage_exceeded" || // if the rule type is one of these, then we have exceeded usage
699
+ ruleType == "plan_entitlement_usage_exceeded");
700
+ return {
701
+ featureUsageExceeded,
702
+ companyId: companyId == null ? void 0 : companyId,
703
+ error: error == null ? void 0 : error,
704
+ featureAllocation: featureAllocation == null ? void 0 : featureAllocation,
705
+ featureUsage: featureUsage == null ? void 0 : featureUsage,
706
+ featureUsagePeriod: featureUsagePeriod == null ? void 0 : featureUsagePeriod,
707
+ featureUsageResetAt: featureUsageResetAt == null ? void 0 : featureUsageResetAt,
708
+ flag,
709
+ flagId: flagId == null ? void 0 : flagId,
710
+ reason,
711
+ ruleId: ruleId == null ? void 0 : ruleId,
712
+ ruleType: ruleType == null ? void 0 : ruleType,
713
+ userId: userId == null ? void 0 : userId,
714
+ value
715
+ };
716
+ };
569
717
  function contextString(context) {
570
718
  const sortedContext = Object.keys(context).reduce((acc, key) => {
571
719
  const sortedKeys = Object.keys(
@@ -589,19 +737,18 @@ var Schematic = class {
589
737
  context = {};
590
738
  eventQueue;
591
739
  eventUrl = "https://c.schematichq.com";
592
- flagListener;
740
+ flagCheckListeners = {};
593
741
  flagValueListeners = {};
594
742
  isPending = true;
595
743
  isPendingListeners = /* @__PURE__ */ new Set();
596
744
  storage;
597
745
  useWebSocket = false;
598
- values = {};
746
+ checks = {};
599
747
  webSocketUrl = "wss://api.schematichq.com";
600
748
  constructor(apiKey, options) {
601
749
  this.apiKey = apiKey;
602
750
  this.eventQueue = [];
603
751
  this.useWebSocket = options?.useWebSocket ?? false;
604
- this.flagListener = options?.flagListener;
605
752
  if (options?.additionalHeaders) {
606
753
  this.additionalHeaders = options.additionalHeaders;
607
754
  }
@@ -651,17 +798,17 @@ var Schematic = class {
651
798
  throw new Error("Network response was not ok");
652
799
  }
653
800
  return response.json();
654
- }).then((data) => {
655
- return data.data.value;
801
+ }).then((response) => {
802
+ return CheckFlagResponseFromJSON(response).data.value;
656
803
  }).catch((error) => {
657
804
  console.error("There was a problem with the fetch operation:", error);
658
805
  return fallback;
659
806
  });
660
807
  }
661
808
  try {
662
- const existingVals = this.values[contextStr];
809
+ const existingVals = this.checks[contextStr];
663
810
  if (this.conn && typeof existingVals !== "undefined" && typeof existingVals[key] !== "undefined") {
664
- return existingVals[key];
811
+ return existingVals[key].value;
665
812
  }
666
813
  try {
667
814
  await this.setContext(context);
@@ -672,8 +819,8 @@ var Schematic = class {
672
819
  );
673
820
  return this.fallbackToRest(key, context, fallback);
674
821
  }
675
- const contextVals = this.values[contextStr] ?? {};
676
- return typeof contextVals[key] === "undefined" ? fallback : contextVals[key];
822
+ const contextVals = this.checks[contextStr] ?? {};
823
+ return contextVals[key]?.value ?? fallback;
677
824
  } catch (error) {
678
825
  console.error("Unexpected error in checkFlag:", error);
679
826
  return fallback;
@@ -697,8 +844,8 @@ var Schematic = class {
697
844
  if (!response.ok) {
698
845
  throw new Error("Network response was not ok");
699
846
  }
700
- const data = await response.json();
701
- return data.data.value;
847
+ const data = CheckFlagResponseFromJSON(await response.json());
848
+ return data?.data?.value ?? false;
702
849
  } catch (error) {
703
850
  console.error("REST API call failed, using fallback value:", error);
704
851
  return fallback;
@@ -725,8 +872,9 @@ var Schematic = class {
725
872
  throw new Error("Network response was not ok");
726
873
  }
727
874
  return response.json();
728
- }).then((data) => {
729
- return (data?.data?.flags ?? []).reduce(
875
+ }).then((responseJson) => {
876
+ const resp = CheckFlagsResponseFromJSON(responseJson);
877
+ return (resp?.data?.flags ?? []).reduce(
730
878
  (accum, flag) => {
731
879
  accum[flag.flag] = flag.value;
732
880
  return accum;
@@ -735,7 +883,7 @@ var Schematic = class {
735
883
  );
736
884
  }).catch((error) => {
737
885
  console.error("There was a problem with the fetch operation:", error);
738
- return false;
886
+ return {};
739
887
  });
740
888
  };
741
889
  /**
@@ -897,18 +1045,15 @@ var Schematic = class {
897
1045
  let resolved = false;
898
1046
  const messageHandler = (event) => {
899
1047
  const message = JSON.parse(event.data);
900
- if (!(contextString(context) in this.values)) {
901
- this.values[contextString(context)] = {};
902
- }
903
- (message.flags ?? []).forEach(
904
- (flag) => {
905
- this.values[contextString(context)][flag.flag] = flag.value;
906
- this.notifyFlagValueListeners(flag.flag, flag.value);
907
- }
908
- );
909
- if (this.flagListener) {
910
- this.flagListener(this.getFlagValues());
1048
+ if (!(contextString(context) in this.checks)) {
1049
+ this.checks[contextString(context)] = {};
911
1050
  }
1051
+ (message.flags ?? []).forEach((flag) => {
1052
+ const flagCheck = CheckFlagReturnFromJSON(flag);
1053
+ this.checks[contextString(context)][flagCheck.flag] = flagCheck;
1054
+ this.notifyFlagCheckListeners(flag.flag, flagCheck);
1055
+ this.notifyFlagValueListeners(flag.flag, flagCheck.value);
1056
+ });
912
1057
  this.setIsPending(false);
913
1058
  if (!resolved) {
914
1059
  resolved = true;
@@ -948,18 +1093,21 @@ var Schematic = class {
948
1093
  setIsPending = (isPending) => {
949
1094
  this.isPending = isPending;
950
1095
  this.isPendingListeners.forEach(
951
- (listener) => notifyListener(listener, isPending)
1096
+ (listener) => notifyPendingListener(listener, isPending)
952
1097
  );
953
1098
  };
1099
+ // flag checks state
1100
+ getFlagCheck = (flagKey) => {
1101
+ const contextStr = contextString(this.context);
1102
+ const checks = this.checks[contextStr] ?? {};
1103
+ return checks[flagKey];
1104
+ };
954
1105
  // flagValues state
955
1106
  getFlagValue = (flagKey) => {
956
- const values = this.getFlagValues();
957
- return values[flagKey];
958
- };
959
- getFlagValues = () => {
960
- const contextStr = contextString(this.context);
961
- return this.values[contextStr] ?? {};
1107
+ const check = this.getFlagCheck(flagKey);
1108
+ return check?.value;
962
1109
  };
1110
+ /** Register an event listener that will be notified with the boolean value for a given flag when this value changes */
963
1111
  addFlagValueListener = (flagKey, listener) => {
964
1112
  if (!(flagKey in this.flagValueListeners)) {
965
1113
  this.flagValueListeners[flagKey] = /* @__PURE__ */ new Set();
@@ -969,12 +1117,40 @@ var Schematic = class {
969
1117
  this.flagValueListeners[flagKey].delete(listener);
970
1118
  };
971
1119
  };
1120
+ /** Register an event listener that will be notified with the full flag check response for a given flag whenever this value changes */
1121
+ addFlagCheckListener = (flagKey, listener) => {
1122
+ if (!(flagKey in this.flagCheckListeners)) {
1123
+ this.flagCheckListeners[flagKey] = /* @__PURE__ */ new Set();
1124
+ }
1125
+ this.flagCheckListeners[flagKey].add(listener);
1126
+ return () => {
1127
+ this.flagCheckListeners[flagKey].delete(listener);
1128
+ };
1129
+ };
1130
+ notifyFlagCheckListeners = (flagKey, check) => {
1131
+ const listeners = this.flagCheckListeners?.[flagKey] ?? [];
1132
+ listeners.forEach((listener) => notifyFlagCheckListener(listener, check));
1133
+ };
972
1134
  notifyFlagValueListeners = (flagKey, value) => {
973
1135
  const listeners = this.flagValueListeners?.[flagKey] ?? [];
974
- listeners.forEach((listener) => notifyListener(listener, value));
1136
+ listeners.forEach((listener) => notifyFlagValueListener(listener, value));
975
1137
  };
976
1138
  };
977
- var notifyListener = (listener, value) => {
1139
+ var notifyPendingListener = (listener, value) => {
1140
+ if (listener.length > 0) {
1141
+ listener(value);
1142
+ } else {
1143
+ listener();
1144
+ }
1145
+ };
1146
+ var notifyFlagCheckListener = (listener, value) => {
1147
+ if (listener.length > 0) {
1148
+ listener(value);
1149
+ } else {
1150
+ listener();
1151
+ }
1152
+ };
1153
+ var notifyFlagValueListener = (listener, value) => {
978
1154
  if (listener.length > 0) {
979
1155
  listener(value);
980
1156
  } else {
@@ -1078,6 +1254,27 @@ var useSchematicFlag = (key, opts) => {
1078
1254
  }, [client, key, fallback]);
1079
1255
  return useSyncExternalStore(subscribe, getSnapshot);
1080
1256
  };
1257
+ var useSchematicEntitlement = (key, opts) => {
1258
+ const client = useSchematicClient(opts);
1259
+ const fallback = opts?.fallback ?? false;
1260
+ const fallbackCheck = useMemo2(
1261
+ () => ({
1262
+ flag: key,
1263
+ reason: "Fallback",
1264
+ value: fallback
1265
+ }),
1266
+ [key, fallback]
1267
+ );
1268
+ const subscribe = useCallback(
1269
+ (callback) => client.addFlagCheckListener(key, callback),
1270
+ [client, key]
1271
+ );
1272
+ const getSnapshot = useCallback(() => {
1273
+ const check = client.getFlagCheck(key);
1274
+ return check ?? fallbackCheck;
1275
+ }, [client, key, fallbackCheck]);
1276
+ return useSyncExternalStore(subscribe, getSnapshot);
1277
+ };
1081
1278
  var useSchematicIsPending = (opts) => {
1082
1279
  const client = useSchematicClient(opts);
1083
1280
  const subscribe = useCallback(
@@ -1088,10 +1285,13 @@ var useSchematicIsPending = (opts) => {
1088
1285
  return useSyncExternalStore(subscribe, getSnapshot);
1089
1286
  };
1090
1287
  export {
1288
+ RuleType,
1091
1289
  Schematic,
1092
1290
  SchematicProvider,
1291
+ UsagePeriod,
1093
1292
  useSchematic,
1094
1293
  useSchematicContext,
1294
+ useSchematicEntitlement,
1095
1295
  useSchematicEvents,
1096
1296
  useSchematicFlag,
1097
1297
  useSchematicIsPending
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schematichq/schematic-react",
3
- "version": "1.0.3",
3
+ "version": "1.1.1",
4
4
  "main": "dist/schematic-react.cjs.js",
5
5
  "module": "dist/schematic-react.esm.js",
6
6
  "types": "dist/schematic-react.d.ts",
@@ -28,7 +28,7 @@
28
28
  "tsc": "npx tsc"
29
29
  },
30
30
  "dependencies": {
31
- "@schematichq/schematic-js": "^1.0.2"
31
+ "@schematichq/schematic-js": "^1.1.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@microsoft/api-extractor": "^7.47.9",