@schematichq/schematic-react 1.0.2 → 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.
- package/README.md +40 -1
- package/dist/schematic-react.cjs.js +394 -120
- package/dist/schematic-react.d.ts +11 -6
- package/dist/schematic-react.esm.js +392 -118
- package/package.json +3 -3
|
@@ -28,17 +28,20 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
|
|
30
30
|
// src/index.ts
|
|
31
|
-
var
|
|
32
|
-
__export(
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
RuleType: () => RuleType,
|
|
33
34
|
Schematic: () => Schematic,
|
|
34
35
|
SchematicProvider: () => SchematicProvider,
|
|
36
|
+
UsagePeriod: () => UsagePeriod,
|
|
35
37
|
useSchematic: () => useSchematic,
|
|
36
38
|
useSchematicContext: () => useSchematicContext,
|
|
37
39
|
useSchematicEvents: () => useSchematicEvents,
|
|
38
40
|
useSchematicFlag: () => useSchematicFlag,
|
|
41
|
+
useSchematicFlagCheck: () => useSchematicFlagCheck,
|
|
39
42
|
useSchematicIsPending: () => useSchematicIsPending
|
|
40
43
|
});
|
|
41
|
-
module.exports = __toCommonJS(
|
|
44
|
+
module.exports = __toCommonJS(index_exports);
|
|
42
45
|
|
|
43
46
|
// node_modules/@schematichq/schematic-js/dist/schematic.esm.js
|
|
44
47
|
var __create2 = Object.create;
|
|
@@ -70,11 +73,12 @@ var require_browser_polyfill = __commonJS({
|
|
|
70
73
|
"node_modules/cross-fetch/dist/browser-polyfill.js"(exports) {
|
|
71
74
|
(function(self2) {
|
|
72
75
|
var irrelevant = function(exports2) {
|
|
73
|
-
var
|
|
76
|
+
var g = typeof globalThis !== "undefined" && globalThis || typeof self2 !== "undefined" && self2 || // eslint-disable-next-line no-undef
|
|
77
|
+
typeof global !== "undefined" && global || {};
|
|
74
78
|
var support = {
|
|
75
|
-
searchParams: "URLSearchParams" in
|
|
76
|
-
iterable: "Symbol" in
|
|
77
|
-
blob: "FileReader" in
|
|
79
|
+
searchParams: "URLSearchParams" in g,
|
|
80
|
+
iterable: "Symbol" in g && "iterator" in Symbol,
|
|
81
|
+
blob: "FileReader" in g && "Blob" in g && function() {
|
|
78
82
|
try {
|
|
79
83
|
new Blob();
|
|
80
84
|
return true;
|
|
@@ -82,8 +86,8 @@ var require_browser_polyfill = __commonJS({
|
|
|
82
86
|
return false;
|
|
83
87
|
}
|
|
84
88
|
}(),
|
|
85
|
-
formData: "FormData" in
|
|
86
|
-
arrayBuffer: "ArrayBuffer" in
|
|
89
|
+
formData: "FormData" in g,
|
|
90
|
+
arrayBuffer: "ArrayBuffer" in g
|
|
87
91
|
};
|
|
88
92
|
function isDataView(obj) {
|
|
89
93
|
return obj && DataView.prototype.isPrototypeOf(obj);
|
|
@@ -141,6 +145,9 @@ var require_browser_polyfill = __commonJS({
|
|
|
141
145
|
}, this);
|
|
142
146
|
} else if (Array.isArray(headers)) {
|
|
143
147
|
headers.forEach(function(header) {
|
|
148
|
+
if (header.length != 2) {
|
|
149
|
+
throw new TypeError("Headers constructor: expected name/value pair to be length 2, found" + header.length);
|
|
150
|
+
}
|
|
144
151
|
this.append(header[0], header[1]);
|
|
145
152
|
}, this);
|
|
146
153
|
} else if (headers) {
|
|
@@ -200,6 +207,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
200
207
|
Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
|
|
201
208
|
}
|
|
202
209
|
function consumed(body) {
|
|
210
|
+
if (body._noBody) return;
|
|
203
211
|
if (body.bodyUsed) {
|
|
204
212
|
return Promise.reject(new TypeError("Already read"));
|
|
205
213
|
}
|
|
@@ -224,14 +232,16 @@ var require_browser_polyfill = __commonJS({
|
|
|
224
232
|
function readBlobAsText(blob) {
|
|
225
233
|
var reader = new FileReader();
|
|
226
234
|
var promise = fileReaderReady(reader);
|
|
227
|
-
|
|
235
|
+
var match = /charset=([A-Za-z0-9_-]+)/.exec(blob.type);
|
|
236
|
+
var encoding = match ? match[1] : "utf-8";
|
|
237
|
+
reader.readAsText(blob, encoding);
|
|
228
238
|
return promise;
|
|
229
239
|
}
|
|
230
240
|
function readArrayBufferAsText(buf) {
|
|
231
241
|
var view = new Uint8Array(buf);
|
|
232
242
|
var chars = new Array(view.length);
|
|
233
|
-
for (var
|
|
234
|
-
chars[
|
|
243
|
+
for (var i = 0; i < view.length; i++) {
|
|
244
|
+
chars[i] = String.fromCharCode(view[i]);
|
|
235
245
|
}
|
|
236
246
|
return chars.join("");
|
|
237
247
|
}
|
|
@@ -250,6 +260,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
250
260
|
this.bodyUsed = this.bodyUsed;
|
|
251
261
|
this._bodyInit = body;
|
|
252
262
|
if (!body) {
|
|
263
|
+
this._noBody = true;
|
|
253
264
|
this._bodyText = "";
|
|
254
265
|
} else if (typeof body === "string") {
|
|
255
266
|
this._bodyText = body;
|
|
@@ -293,27 +304,28 @@ var require_browser_polyfill = __commonJS({
|
|
|
293
304
|
return Promise.resolve(new Blob([this._bodyText]));
|
|
294
305
|
}
|
|
295
306
|
};
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
} else {
|
|
310
|
-
return Promise.resolve(this._bodyArrayBuffer);
|
|
311
|
-
}
|
|
307
|
+
}
|
|
308
|
+
this.arrayBuffer = function() {
|
|
309
|
+
if (this._bodyArrayBuffer) {
|
|
310
|
+
var isConsumed = consumed(this);
|
|
311
|
+
if (isConsumed) {
|
|
312
|
+
return isConsumed;
|
|
313
|
+
} else if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
|
|
314
|
+
return Promise.resolve(
|
|
315
|
+
this._bodyArrayBuffer.buffer.slice(
|
|
316
|
+
this._bodyArrayBuffer.byteOffset,
|
|
317
|
+
this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength
|
|
318
|
+
)
|
|
319
|
+
);
|
|
312
320
|
} else {
|
|
313
|
-
return
|
|
321
|
+
return Promise.resolve(this._bodyArrayBuffer);
|
|
314
322
|
}
|
|
315
|
-
}
|
|
316
|
-
|
|
323
|
+
} else if (support.blob) {
|
|
324
|
+
return this.blob().then(readBlobAsArrayBuffer);
|
|
325
|
+
} else {
|
|
326
|
+
throw new Error("could not read as ArrayBuffer");
|
|
327
|
+
}
|
|
328
|
+
};
|
|
317
329
|
this.text = function() {
|
|
318
330
|
var rejected = consumed(this);
|
|
319
331
|
if (rejected) {
|
|
@@ -339,7 +351,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
339
351
|
};
|
|
340
352
|
return this;
|
|
341
353
|
}
|
|
342
|
-
var methods = ["DELETE", "GET", "HEAD", "OPTIONS", "POST", "PUT"];
|
|
354
|
+
var methods = ["CONNECT", "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT", "TRACE"];
|
|
343
355
|
function normalizeMethod(method) {
|
|
344
356
|
var upcased = method.toUpperCase();
|
|
345
357
|
return methods.indexOf(upcased) > -1 ? upcased : method;
|
|
@@ -375,7 +387,12 @@ var require_browser_polyfill = __commonJS({
|
|
|
375
387
|
}
|
|
376
388
|
this.method = normalizeMethod(options.method || this.method || "GET");
|
|
377
389
|
this.mode = options.mode || this.mode || null;
|
|
378
|
-
this.signal = options.signal || this.signal
|
|
390
|
+
this.signal = options.signal || this.signal || function() {
|
|
391
|
+
if ("AbortController" in g) {
|
|
392
|
+
var ctrl = new AbortController();
|
|
393
|
+
return ctrl.signal;
|
|
394
|
+
}
|
|
395
|
+
}();
|
|
379
396
|
this.referrer = null;
|
|
380
397
|
if ((this.method === "GET" || this.method === "HEAD") && body) {
|
|
381
398
|
throw new TypeError("Body not allowed for GET or HEAD requests");
|
|
@@ -418,7 +435,11 @@ var require_browser_polyfill = __commonJS({
|
|
|
418
435
|
var key = parts.shift().trim();
|
|
419
436
|
if (key) {
|
|
420
437
|
var value = parts.join(":").trim();
|
|
421
|
-
|
|
438
|
+
try {
|
|
439
|
+
headers.append(key, value);
|
|
440
|
+
} catch (error) {
|
|
441
|
+
console.warn("Response " + error.message);
|
|
442
|
+
}
|
|
422
443
|
}
|
|
423
444
|
});
|
|
424
445
|
return headers;
|
|
@@ -433,6 +454,9 @@ var require_browser_polyfill = __commonJS({
|
|
|
433
454
|
}
|
|
434
455
|
this.type = "default";
|
|
435
456
|
this.status = options.status === void 0 ? 200 : options.status;
|
|
457
|
+
if (this.status < 200 || this.status > 599) {
|
|
458
|
+
throw new RangeError("Failed to construct 'Response': The status provided (0) is outside the range [200, 599].");
|
|
459
|
+
}
|
|
436
460
|
this.ok = this.status >= 200 && this.status < 300;
|
|
437
461
|
this.statusText = options.statusText === void 0 ? "" : "" + options.statusText;
|
|
438
462
|
this.headers = new Headers(options.headers);
|
|
@@ -449,7 +473,9 @@ var require_browser_polyfill = __commonJS({
|
|
|
449
473
|
});
|
|
450
474
|
};
|
|
451
475
|
Response.error = function() {
|
|
452
|
-
var response = new Response(null, { status:
|
|
476
|
+
var response = new Response(null, { status: 200, statusText: "" });
|
|
477
|
+
response.ok = false;
|
|
478
|
+
response.status = 0;
|
|
453
479
|
response.type = "error";
|
|
454
480
|
return response;
|
|
455
481
|
};
|
|
@@ -460,7 +486,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
460
486
|
}
|
|
461
487
|
return new Response(null, { status, headers: { location: url } });
|
|
462
488
|
};
|
|
463
|
-
exports2.DOMException =
|
|
489
|
+
exports2.DOMException = g.DOMException;
|
|
464
490
|
try {
|
|
465
491
|
new exports2.DOMException();
|
|
466
492
|
} catch (err) {
|
|
@@ -485,10 +511,14 @@ var require_browser_polyfill = __commonJS({
|
|
|
485
511
|
}
|
|
486
512
|
xhr.onload = function() {
|
|
487
513
|
var options = {
|
|
488
|
-
status: xhr.status,
|
|
489
514
|
statusText: xhr.statusText,
|
|
490
515
|
headers: parseHeaders(xhr.getAllResponseHeaders() || "")
|
|
491
516
|
};
|
|
517
|
+
if (request.url.indexOf("file://") === 0 && (xhr.status < 200 || xhr.status > 599)) {
|
|
518
|
+
options.status = 200;
|
|
519
|
+
} else {
|
|
520
|
+
options.status = xhr.status;
|
|
521
|
+
}
|
|
492
522
|
options.url = "responseURL" in xhr ? xhr.responseURL : options.headers.get("X-Request-URL");
|
|
493
523
|
var body = "response" in xhr ? xhr.response : xhr.responseText;
|
|
494
524
|
setTimeout(function() {
|
|
@@ -502,7 +532,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
502
532
|
};
|
|
503
533
|
xhr.ontimeout = function() {
|
|
504
534
|
setTimeout(function() {
|
|
505
|
-
reject(new TypeError("Network request
|
|
535
|
+
reject(new TypeError("Network request timed out"));
|
|
506
536
|
}, 0);
|
|
507
537
|
};
|
|
508
538
|
xhr.onabort = function() {
|
|
@@ -512,7 +542,7 @@ var require_browser_polyfill = __commonJS({
|
|
|
512
542
|
};
|
|
513
543
|
function fixUrl(url) {
|
|
514
544
|
try {
|
|
515
|
-
return url === "" &&
|
|
545
|
+
return url === "" && g.location.href ? g.location.href : url;
|
|
516
546
|
} catch (e) {
|
|
517
547
|
return url;
|
|
518
548
|
}
|
|
@@ -526,14 +556,21 @@ var require_browser_polyfill = __commonJS({
|
|
|
526
556
|
if ("responseType" in xhr) {
|
|
527
557
|
if (support.blob) {
|
|
528
558
|
xhr.responseType = "blob";
|
|
529
|
-
} else if (support.arrayBuffer
|
|
559
|
+
} else if (support.arrayBuffer) {
|
|
530
560
|
xhr.responseType = "arraybuffer";
|
|
531
561
|
}
|
|
532
562
|
}
|
|
533
|
-
if (init && typeof init.headers === "object" && !(init.headers instanceof Headers)) {
|
|
563
|
+
if (init && typeof init.headers === "object" && !(init.headers instanceof Headers || g.Headers && init.headers instanceof g.Headers)) {
|
|
564
|
+
var names = [];
|
|
534
565
|
Object.getOwnPropertyNames(init.headers).forEach(function(name) {
|
|
566
|
+
names.push(normalizeName(name));
|
|
535
567
|
xhr.setRequestHeader(name, normalizeValue(init.headers[name]));
|
|
536
568
|
});
|
|
569
|
+
request.headers.forEach(function(value, name) {
|
|
570
|
+
if (names.indexOf(name) === -1) {
|
|
571
|
+
xhr.setRequestHeader(name, value);
|
|
572
|
+
}
|
|
573
|
+
});
|
|
537
574
|
} else {
|
|
538
575
|
request.headers.forEach(function(value, name) {
|
|
539
576
|
xhr.setRequestHeader(name, value);
|
|
@@ -551,11 +588,11 @@ var require_browser_polyfill = __commonJS({
|
|
|
551
588
|
});
|
|
552
589
|
}
|
|
553
590
|
fetch2.polyfill = true;
|
|
554
|
-
if (!
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
591
|
+
if (!g.fetch) {
|
|
592
|
+
g.fetch = fetch2;
|
|
593
|
+
g.Headers = Headers;
|
|
594
|
+
g.Request = Request;
|
|
595
|
+
g.Response = Response;
|
|
559
596
|
}
|
|
560
597
|
exports2.Headers = Headers;
|
|
561
598
|
exports2.Request = Request;
|
|
@@ -567,10 +604,9 @@ var require_browser_polyfill = __commonJS({
|
|
|
567
604
|
}
|
|
568
605
|
});
|
|
569
606
|
var byteToHex = [];
|
|
570
|
-
for (i = 0; i < 256; ++i) {
|
|
607
|
+
for (let i = 0; i < 256; ++i) {
|
|
571
608
|
byteToHex.push((i + 256).toString(16).slice(1));
|
|
572
609
|
}
|
|
573
|
-
var i;
|
|
574
610
|
function unsafeStringify(arr, offset = 0) {
|
|
575
611
|
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();
|
|
576
612
|
}
|
|
@@ -578,29 +614,33 @@ var getRandomValues;
|
|
|
578
614
|
var rnds8 = new Uint8Array(16);
|
|
579
615
|
function rng() {
|
|
580
616
|
if (!getRandomValues) {
|
|
581
|
-
|
|
582
|
-
if (!getRandomValues) {
|
|
617
|
+
if (typeof crypto === "undefined" || !crypto.getRandomValues) {
|
|
583
618
|
throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");
|
|
584
619
|
}
|
|
620
|
+
getRandomValues = crypto.getRandomValues.bind(crypto);
|
|
585
621
|
}
|
|
586
622
|
return getRandomValues(rnds8);
|
|
587
623
|
}
|
|
588
624
|
var randomUUID = typeof crypto !== "undefined" && crypto.randomUUID && crypto.randomUUID.bind(crypto);
|
|
589
|
-
var native_default = {
|
|
590
|
-
randomUUID
|
|
591
|
-
};
|
|
625
|
+
var native_default = { randomUUID };
|
|
592
626
|
function v4(options, buf, offset) {
|
|
593
627
|
if (native_default.randomUUID && !buf && !options) {
|
|
594
628
|
return native_default.randomUUID();
|
|
595
629
|
}
|
|
596
630
|
options = options || {};
|
|
597
|
-
|
|
631
|
+
const rnds = options.random ?? options.rng?.() ?? rng();
|
|
632
|
+
if (rnds.length < 16) {
|
|
633
|
+
throw new Error("Random bytes length must be >= 16");
|
|
634
|
+
}
|
|
598
635
|
rnds[6] = rnds[6] & 15 | 64;
|
|
599
636
|
rnds[8] = rnds[8] & 63 | 128;
|
|
600
637
|
if (buf) {
|
|
601
638
|
offset = offset || 0;
|
|
602
|
-
|
|
603
|
-
|
|
639
|
+
if (offset < 0 || offset + 16 > buf.length) {
|
|
640
|
+
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
|
|
641
|
+
}
|
|
642
|
+
for (let i = 0; i < 16; ++i) {
|
|
643
|
+
buf[offset + i] = rnds[i];
|
|
604
644
|
}
|
|
605
645
|
return buf;
|
|
606
646
|
}
|
|
@@ -608,6 +648,117 @@ function v4(options, buf, offset) {
|
|
|
608
648
|
}
|
|
609
649
|
var v4_default = v4;
|
|
610
650
|
var import_polyfill = __toESM2(require_browser_polyfill());
|
|
651
|
+
function CheckFlagResponseDataFromJSON(json) {
|
|
652
|
+
return CheckFlagResponseDataFromJSONTyped(json, false);
|
|
653
|
+
}
|
|
654
|
+
function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
655
|
+
if (json == null) {
|
|
656
|
+
return json;
|
|
657
|
+
}
|
|
658
|
+
return {
|
|
659
|
+
companyId: json["company_id"] == null ? void 0 : json["company_id"],
|
|
660
|
+
error: json["error"] == null ? void 0 : json["error"],
|
|
661
|
+
featureAllocation: json["feature_allocation"] == null ? void 0 : json["feature_allocation"],
|
|
662
|
+
featureUsage: json["feature_usage"] == null ? void 0 : json["feature_usage"],
|
|
663
|
+
featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : json["feature_usage_period"],
|
|
664
|
+
featureUsageResetAt: json["feature_usage_reset_at"] == null ? void 0 : new Date(json["feature_usage_reset_at"]),
|
|
665
|
+
flag: json["flag"],
|
|
666
|
+
flagId: json["flag_id"] == null ? void 0 : json["flag_id"],
|
|
667
|
+
reason: json["reason"],
|
|
668
|
+
ruleId: json["rule_id"] == null ? void 0 : json["rule_id"],
|
|
669
|
+
ruleType: json["rule_type"] == null ? void 0 : json["rule_type"],
|
|
670
|
+
userId: json["user_id"] == null ? void 0 : json["user_id"],
|
|
671
|
+
value: json["value"]
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
function CheckFlagResponseFromJSON(json) {
|
|
675
|
+
return CheckFlagResponseFromJSONTyped(json, false);
|
|
676
|
+
}
|
|
677
|
+
function CheckFlagResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
678
|
+
if (json == null) {
|
|
679
|
+
return json;
|
|
680
|
+
}
|
|
681
|
+
return {
|
|
682
|
+
data: CheckFlagResponseDataFromJSON(json["data"]),
|
|
683
|
+
params: json["params"]
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
function CheckFlagsResponseDataFromJSON(json) {
|
|
687
|
+
return CheckFlagsResponseDataFromJSONTyped(json, false);
|
|
688
|
+
}
|
|
689
|
+
function CheckFlagsResponseDataFromJSONTyped(json, ignoreDiscriminator) {
|
|
690
|
+
if (json == null) {
|
|
691
|
+
return json;
|
|
692
|
+
}
|
|
693
|
+
return {
|
|
694
|
+
flags: json["flags"].map(CheckFlagResponseDataFromJSON)
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
function CheckFlagsResponseFromJSON(json) {
|
|
698
|
+
return CheckFlagsResponseFromJSONTyped(json, false);
|
|
699
|
+
}
|
|
700
|
+
function CheckFlagsResponseFromJSONTyped(json, ignoreDiscriminator) {
|
|
701
|
+
if (json == null) {
|
|
702
|
+
return json;
|
|
703
|
+
}
|
|
704
|
+
return {
|
|
705
|
+
data: CheckFlagsResponseDataFromJSON(json["data"]),
|
|
706
|
+
params: json["params"]
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
var RuleType = /* @__PURE__ */ ((RuleType2) => {
|
|
710
|
+
RuleType2["GLOBAL_OVERRIDE"] = "global_override";
|
|
711
|
+
RuleType2["COMPANY_OVERRIDE"] = "company_override";
|
|
712
|
+
RuleType2["COMPANY_OVERRIDE_USAGE_EXCEEDED"] = "company_override_usage_exceeded";
|
|
713
|
+
RuleType2["PLAN_ENTITLEMENT"] = "plan_entitlement";
|
|
714
|
+
RuleType2["PLAN_ENTITLEMENT_USAGE_EXCEEDED"] = "plan_entitlement_usage_exceeded";
|
|
715
|
+
RuleType2["STANDARD"] = "standard";
|
|
716
|
+
RuleType2["DEFAULT"] = "default";
|
|
717
|
+
return RuleType2;
|
|
718
|
+
})(RuleType || {});
|
|
719
|
+
var UsagePeriod = /* @__PURE__ */ ((UsagePeriod2) => {
|
|
720
|
+
UsagePeriod2["ALL_TIME"] = "all_time";
|
|
721
|
+
UsagePeriod2["CURRENT_DAY"] = "current_day";
|
|
722
|
+
UsagePeriod2["CURRENT_MONTH"] = "current_month";
|
|
723
|
+
UsagePeriod2["CURRENT_WEEK"] = "current_week";
|
|
724
|
+
return UsagePeriod2;
|
|
725
|
+
})(UsagePeriod || {});
|
|
726
|
+
var CheckFlagReturnFromJSON = (json) => {
|
|
727
|
+
const {
|
|
728
|
+
companyId,
|
|
729
|
+
error,
|
|
730
|
+
featureAllocation,
|
|
731
|
+
featureUsage,
|
|
732
|
+
featureUsagePeriod,
|
|
733
|
+
featureUsageResetAt,
|
|
734
|
+
flag,
|
|
735
|
+
flagId,
|
|
736
|
+
reason,
|
|
737
|
+
ruleId,
|
|
738
|
+
ruleType,
|
|
739
|
+
userId,
|
|
740
|
+
value
|
|
741
|
+
} = CheckFlagResponseDataFromJSON(json);
|
|
742
|
+
const featureUsageExceeded = !value && // if flag is not false, then we haven't exceeded usage
|
|
743
|
+
(ruleType == "company_override_usage_exceeded" || // if the rule type is one of these, then we have exceeded usage
|
|
744
|
+
ruleType == "plan_entitlement_usage_exceeded");
|
|
745
|
+
return {
|
|
746
|
+
featureUsageExceeded,
|
|
747
|
+
companyId: companyId == null ? void 0 : companyId,
|
|
748
|
+
error: error == null ? void 0 : error,
|
|
749
|
+
featureAllocation: featureAllocation == null ? void 0 : featureAllocation,
|
|
750
|
+
featureUsage: featureUsage == null ? void 0 : featureUsage,
|
|
751
|
+
featureUsagePeriod: featureUsagePeriod == null ? void 0 : featureUsagePeriod,
|
|
752
|
+
featureUsageResetAt: featureUsageResetAt == null ? void 0 : featureUsageResetAt,
|
|
753
|
+
flag,
|
|
754
|
+
flagId: flagId == null ? void 0 : flagId,
|
|
755
|
+
reason,
|
|
756
|
+
ruleId: ruleId == null ? void 0 : ruleId,
|
|
757
|
+
ruleType: ruleType == null ? void 0 : ruleType,
|
|
758
|
+
userId: userId == null ? void 0 : userId,
|
|
759
|
+
value
|
|
760
|
+
};
|
|
761
|
+
};
|
|
611
762
|
function contextString(context) {
|
|
612
763
|
const sortedContext = Object.keys(context).reduce((acc, key) => {
|
|
613
764
|
const sortedKeys = Object.keys(
|
|
@@ -631,19 +782,18 @@ var Schematic = class {
|
|
|
631
782
|
context = {};
|
|
632
783
|
eventQueue;
|
|
633
784
|
eventUrl = "https://c.schematichq.com";
|
|
634
|
-
|
|
785
|
+
flagCheckListeners = {};
|
|
635
786
|
flagValueListeners = {};
|
|
636
787
|
isPending = true;
|
|
637
788
|
isPendingListeners = /* @__PURE__ */ new Set();
|
|
638
789
|
storage;
|
|
639
790
|
useWebSocket = false;
|
|
640
|
-
|
|
791
|
+
checks = {};
|
|
641
792
|
webSocketUrl = "wss://api.schematichq.com";
|
|
642
793
|
constructor(apiKey, options) {
|
|
643
794
|
this.apiKey = apiKey;
|
|
644
795
|
this.eventQueue = [];
|
|
645
796
|
this.useWebSocket = options?.useWebSocket ?? false;
|
|
646
|
-
this.flagListener = options?.flagListener;
|
|
647
797
|
if (options?.additionalHeaders) {
|
|
648
798
|
this.additionalHeaders = options.additionalHeaders;
|
|
649
799
|
}
|
|
@@ -667,37 +817,89 @@ var Schematic = class {
|
|
|
667
817
|
});
|
|
668
818
|
}
|
|
669
819
|
}
|
|
670
|
-
|
|
671
|
-
|
|
820
|
+
/**
|
|
821
|
+
* Get value for a single flag.
|
|
822
|
+
* In WebSocket mode, returns cached values if connection is active, otherwise establishes
|
|
823
|
+
* new connection and then returns the requestedvalue. Falls back to REST API if WebSocket
|
|
824
|
+
* connection fails.
|
|
825
|
+
* In REST mode, makes an API call for each check.
|
|
826
|
+
*/
|
|
672
827
|
async checkFlag(options) {
|
|
673
828
|
const { fallback = false, key } = options;
|
|
674
829
|
const context = options.context || this.context;
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
830
|
+
const contextStr = contextString(context);
|
|
831
|
+
if (!this.useWebSocket) {
|
|
832
|
+
const requestUrl = `${this.apiUrl}/flags/${key}/check`;
|
|
833
|
+
return fetch(requestUrl, {
|
|
834
|
+
method: "POST",
|
|
835
|
+
headers: {
|
|
836
|
+
...this.additionalHeaders ?? {},
|
|
837
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
838
|
+
"X-Schematic-Api-Key": this.apiKey
|
|
839
|
+
},
|
|
840
|
+
body: JSON.stringify(context)
|
|
841
|
+
}).then((response) => {
|
|
842
|
+
if (!response.ok) {
|
|
843
|
+
throw new Error("Network response was not ok");
|
|
844
|
+
}
|
|
845
|
+
return response.json();
|
|
846
|
+
}).then((response) => {
|
|
847
|
+
return CheckFlagResponseFromJSON(response).data.value;
|
|
848
|
+
}).catch((error) => {
|
|
849
|
+
console.error("There was a problem with the fetch operation:", error);
|
|
850
|
+
return fallback;
|
|
851
|
+
});
|
|
678
852
|
}
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
|
|
853
|
+
try {
|
|
854
|
+
const existingVals = this.checks[contextStr];
|
|
855
|
+
if (this.conn && typeof existingVals !== "undefined" && typeof existingVals[key] !== "undefined") {
|
|
856
|
+
return existingVals[key].value;
|
|
857
|
+
}
|
|
858
|
+
try {
|
|
859
|
+
await this.setContext(context);
|
|
860
|
+
} catch (error) {
|
|
861
|
+
console.error(
|
|
862
|
+
"WebSocket connection failed, falling back to REST:",
|
|
863
|
+
error
|
|
864
|
+
);
|
|
865
|
+
return this.fallbackToRest(key, context, fallback);
|
|
866
|
+
}
|
|
867
|
+
const contextVals = this.checks[contextStr] ?? {};
|
|
868
|
+
return contextVals[key]?.value ?? fallback;
|
|
869
|
+
} catch (error) {
|
|
870
|
+
console.error("Unexpected error in checkFlag:", error);
|
|
871
|
+
return fallback;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* Helper method for falling back to REST API when WebSocket connection fails
|
|
876
|
+
*/
|
|
877
|
+
async fallbackToRest(key, context, fallback) {
|
|
878
|
+
try {
|
|
879
|
+
const requestUrl = `${this.apiUrl}/flags/${key}/check`;
|
|
880
|
+
const response = await fetch(requestUrl, {
|
|
881
|
+
method: "POST",
|
|
882
|
+
headers: {
|
|
883
|
+
...this.additionalHeaders ?? {},
|
|
884
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
885
|
+
"X-Schematic-Api-Key": this.apiKey
|
|
886
|
+
},
|
|
887
|
+
body: JSON.stringify(context)
|
|
888
|
+
});
|
|
689
889
|
if (!response.ok) {
|
|
690
890
|
throw new Error("Network response was not ok");
|
|
691
891
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
console.error("There was a problem with the fetch operation:", error);
|
|
892
|
+
const data = CheckFlagResponseFromJSON(await response.json());
|
|
893
|
+
return data?.data?.value ?? false;
|
|
894
|
+
} catch (error) {
|
|
895
|
+
console.error("REST API call failed, using fallback value:", error);
|
|
697
896
|
return fallback;
|
|
698
|
-
}
|
|
897
|
+
}
|
|
699
898
|
}
|
|
700
|
-
|
|
899
|
+
/**
|
|
900
|
+
* Make an API call to fetch all flag values for a given context.
|
|
901
|
+
* Recommended for use in REST mode only.
|
|
902
|
+
*/
|
|
701
903
|
checkFlags = async (context) => {
|
|
702
904
|
context = context || this.context;
|
|
703
905
|
const requestUrl = `${this.apiUrl}/flags/check`;
|
|
@@ -715,8 +917,9 @@ var Schematic = class {
|
|
|
715
917
|
throw new Error("Network response was not ok");
|
|
716
918
|
}
|
|
717
919
|
return response.json();
|
|
718
|
-
}).then((
|
|
719
|
-
|
|
920
|
+
}).then((responseJson) => {
|
|
921
|
+
const resp = CheckFlagsResponseFromJSON(responseJson);
|
|
922
|
+
return (resp?.data?.flags ?? []).reduce(
|
|
720
923
|
(accum, flag) => {
|
|
721
924
|
accum[flag.flag] = flag.value;
|
|
722
925
|
return accum;
|
|
@@ -725,21 +928,33 @@ var Schematic = class {
|
|
|
725
928
|
);
|
|
726
929
|
}).catch((error) => {
|
|
727
930
|
console.error("There was a problem with the fetch operation:", error);
|
|
728
|
-
return
|
|
931
|
+
return {};
|
|
729
932
|
});
|
|
730
933
|
};
|
|
731
|
-
|
|
934
|
+
/**
|
|
935
|
+
* Send an identify event.
|
|
936
|
+
* This will set the context for subsequent flag evaluation and events, and will also
|
|
937
|
+
* send an identify event to the Schematic API which will upsert a user and company.
|
|
938
|
+
*/
|
|
732
939
|
identify = (body) => {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
940
|
+
try {
|
|
941
|
+
this.setContext({
|
|
942
|
+
company: body.company?.keys,
|
|
943
|
+
user: body.keys
|
|
944
|
+
});
|
|
945
|
+
} catch (error) {
|
|
946
|
+
console.error("Error setting context:", error);
|
|
947
|
+
}
|
|
737
948
|
return this.handleEvent("identify", body);
|
|
738
949
|
};
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
950
|
+
/**
|
|
951
|
+
* Set the flag evaluation context.
|
|
952
|
+
* In WebSocket mode, this will:
|
|
953
|
+
* 1. Open a websocket connection if not already open
|
|
954
|
+
* 2. Send the context to the server
|
|
955
|
+
* 3. Wait for initial flag values to be returned
|
|
956
|
+
* The promise resolves when initial flag values are received.
|
|
957
|
+
*/
|
|
743
958
|
setContext = async (context) => {
|
|
744
959
|
if (!this.useWebSocket) {
|
|
745
960
|
this.context = context;
|
|
@@ -753,10 +968,14 @@ var Schematic = class {
|
|
|
753
968
|
const socket = await this.conn;
|
|
754
969
|
await this.wsSendMessage(socket, context);
|
|
755
970
|
} catch (error) {
|
|
756
|
-
console.error("
|
|
971
|
+
console.error("Failed to establish WebSocket connection:", error);
|
|
972
|
+
throw error;
|
|
757
973
|
}
|
|
758
974
|
};
|
|
759
|
-
|
|
975
|
+
/**
|
|
976
|
+
* Send a track event
|
|
977
|
+
* Track usage for a company and/or user.
|
|
978
|
+
*/
|
|
760
979
|
track = (body) => {
|
|
761
980
|
const { company, user, event, traits } = body;
|
|
762
981
|
return this.handleEvent("track", {
|
|
@@ -828,6 +1047,9 @@ var Schematic = class {
|
|
|
828
1047
|
/**
|
|
829
1048
|
* Websocket management
|
|
830
1049
|
*/
|
|
1050
|
+
/**
|
|
1051
|
+
* If using websocket mode, close the connection when done.
|
|
1052
|
+
*/
|
|
831
1053
|
cleanup = async () => {
|
|
832
1054
|
if (this.conn) {
|
|
833
1055
|
try {
|
|
@@ -868,18 +1090,15 @@ var Schematic = class {
|
|
|
868
1090
|
let resolved = false;
|
|
869
1091
|
const messageHandler = (event) => {
|
|
870
1092
|
const message = JSON.parse(event.data);
|
|
871
|
-
if (!(contextString(context) in this.
|
|
872
|
-
this.
|
|
873
|
-
}
|
|
874
|
-
(message.flags ?? []).forEach(
|
|
875
|
-
(flag) => {
|
|
876
|
-
this.values[contextString(context)][flag.flag] = flag.value;
|
|
877
|
-
this.notifyFlagValueListeners(flag.flag, flag.value);
|
|
878
|
-
}
|
|
879
|
-
);
|
|
880
|
-
if (this.flagListener) {
|
|
881
|
-
this.flagListener(this.getFlagValues());
|
|
1093
|
+
if (!(contextString(context) in this.checks)) {
|
|
1094
|
+
this.checks[contextString(context)] = {};
|
|
882
1095
|
}
|
|
1096
|
+
(message.flags ?? []).forEach((flag) => {
|
|
1097
|
+
const flagCheck = CheckFlagReturnFromJSON(flag);
|
|
1098
|
+
this.checks[contextString(context)][flagCheck.flag] = flagCheck;
|
|
1099
|
+
this.notifyFlagCheckListeners(flag.flag, flagCheck);
|
|
1100
|
+
this.notifyFlagValueListeners(flag.flag, flagCheck.value);
|
|
1101
|
+
});
|
|
883
1102
|
this.setIsPending(false);
|
|
884
1103
|
if (!resolved) {
|
|
885
1104
|
resolved = true;
|
|
@@ -919,18 +1138,21 @@ var Schematic = class {
|
|
|
919
1138
|
setIsPending = (isPending) => {
|
|
920
1139
|
this.isPending = isPending;
|
|
921
1140
|
this.isPendingListeners.forEach(
|
|
922
|
-
(listener) =>
|
|
1141
|
+
(listener) => notifyPendingListener(listener, isPending)
|
|
923
1142
|
);
|
|
924
1143
|
};
|
|
1144
|
+
// flag checks state
|
|
1145
|
+
getFlagCheck = (flagKey) => {
|
|
1146
|
+
const contextStr = contextString(this.context);
|
|
1147
|
+
const checks = this.checks[contextStr] ?? {};
|
|
1148
|
+
return checks[flagKey];
|
|
1149
|
+
};
|
|
925
1150
|
// flagValues state
|
|
926
1151
|
getFlagValue = (flagKey) => {
|
|
927
|
-
const
|
|
928
|
-
return
|
|
929
|
-
};
|
|
930
|
-
getFlagValues = () => {
|
|
931
|
-
const contextStr = contextString(this.context);
|
|
932
|
-
return this.values[contextStr] ?? {};
|
|
1152
|
+
const check = this.getFlagCheck(flagKey);
|
|
1153
|
+
return check?.value;
|
|
933
1154
|
};
|
|
1155
|
+
/** Register an event listener that will be notified with the boolean value for a given flag when this value changes */
|
|
934
1156
|
addFlagValueListener = (flagKey, listener) => {
|
|
935
1157
|
if (!(flagKey in this.flagValueListeners)) {
|
|
936
1158
|
this.flagValueListeners[flagKey] = /* @__PURE__ */ new Set();
|
|
@@ -940,12 +1162,40 @@ var Schematic = class {
|
|
|
940
1162
|
this.flagValueListeners[flagKey].delete(listener);
|
|
941
1163
|
};
|
|
942
1164
|
};
|
|
1165
|
+
/** Register an event listener that will be notified with the full flag check response for a given flag whenever this value changes */
|
|
1166
|
+
addFlagCheckListener = (flagKey, listener) => {
|
|
1167
|
+
if (!(flagKey in this.flagCheckListeners)) {
|
|
1168
|
+
this.flagCheckListeners[flagKey] = /* @__PURE__ */ new Set();
|
|
1169
|
+
}
|
|
1170
|
+
this.flagCheckListeners[flagKey].add(listener);
|
|
1171
|
+
return () => {
|
|
1172
|
+
this.flagCheckListeners[flagKey].delete(listener);
|
|
1173
|
+
};
|
|
1174
|
+
};
|
|
1175
|
+
notifyFlagCheckListeners = (flagKey, check) => {
|
|
1176
|
+
const listeners = this.flagCheckListeners?.[flagKey] ?? [];
|
|
1177
|
+
listeners.forEach((listener) => notifyFlagCheckListener(listener, check));
|
|
1178
|
+
};
|
|
943
1179
|
notifyFlagValueListeners = (flagKey, value) => {
|
|
944
1180
|
const listeners = this.flagValueListeners?.[flagKey] ?? [];
|
|
945
|
-
listeners.forEach((listener) =>
|
|
1181
|
+
listeners.forEach((listener) => notifyFlagValueListener(listener, value));
|
|
946
1182
|
};
|
|
947
1183
|
};
|
|
948
|
-
var
|
|
1184
|
+
var notifyPendingListener = (listener, value) => {
|
|
1185
|
+
if (listener.length > 0) {
|
|
1186
|
+
listener(value);
|
|
1187
|
+
} else {
|
|
1188
|
+
listener();
|
|
1189
|
+
}
|
|
1190
|
+
};
|
|
1191
|
+
var notifyFlagCheckListener = (listener, value) => {
|
|
1192
|
+
if (listener.length > 0) {
|
|
1193
|
+
listener(value);
|
|
1194
|
+
} else {
|
|
1195
|
+
listener();
|
|
1196
|
+
}
|
|
1197
|
+
};
|
|
1198
|
+
var notifyFlagValueListener = (listener, value) => {
|
|
949
1199
|
if (listener.length > 0) {
|
|
950
1200
|
listener(value);
|
|
951
1201
|
} else {
|
|
@@ -965,16 +1215,19 @@ var SchematicProvider = ({
|
|
|
965
1215
|
publishableKey,
|
|
966
1216
|
...clientOpts
|
|
967
1217
|
}) => {
|
|
1218
|
+
const initialOptsRef = (0, import_react.useRef)({
|
|
1219
|
+
publishableKey,
|
|
1220
|
+
useWebSocket: clientOpts.useWebSocket ?? true,
|
|
1221
|
+
...clientOpts
|
|
1222
|
+
});
|
|
968
1223
|
const client = (0, import_react.useMemo)(() => {
|
|
969
|
-
const { useWebSocket = true } = clientOpts;
|
|
970
1224
|
if (providedClient) {
|
|
971
1225
|
return providedClient;
|
|
972
1226
|
}
|
|
973
|
-
return new Schematic(publishableKey, {
|
|
974
|
-
|
|
975
|
-
...clientOpts
|
|
1227
|
+
return new Schematic(initialOptsRef.current.publishableKey, {
|
|
1228
|
+
...initialOptsRef.current
|
|
976
1229
|
});
|
|
977
|
-
}, [providedClient
|
|
1230
|
+
}, [providedClient]);
|
|
978
1231
|
(0, import_react.useEffect)(() => {
|
|
979
1232
|
return () => {
|
|
980
1233
|
if (!providedClient) {
|
|
@@ -1046,6 +1299,27 @@ var useSchematicFlag = (key, opts) => {
|
|
|
1046
1299
|
}, [client, key, fallback]);
|
|
1047
1300
|
return (0, import_react2.useSyncExternalStore)(subscribe, getSnapshot);
|
|
1048
1301
|
};
|
|
1302
|
+
var useSchematicFlagCheck = (key, opts) => {
|
|
1303
|
+
const client = useSchematicClient(opts);
|
|
1304
|
+
const fallback = opts?.fallback ?? false;
|
|
1305
|
+
const fallbackCheck = (0, import_react2.useMemo)(
|
|
1306
|
+
() => ({
|
|
1307
|
+
flag: key,
|
|
1308
|
+
reason: "Fallback",
|
|
1309
|
+
value: fallback
|
|
1310
|
+
}),
|
|
1311
|
+
[key, fallback]
|
|
1312
|
+
);
|
|
1313
|
+
const subscribe = (0, import_react2.useCallback)(
|
|
1314
|
+
(callback) => client.addFlagCheckListener(key, callback),
|
|
1315
|
+
[client, key]
|
|
1316
|
+
);
|
|
1317
|
+
const getSnapshot = (0, import_react2.useCallback)(() => {
|
|
1318
|
+
const check = client.getFlagCheck(key);
|
|
1319
|
+
return check ?? fallbackCheck;
|
|
1320
|
+
}, [client, key, fallbackCheck]);
|
|
1321
|
+
return (0, import_react2.useSyncExternalStore)(subscribe, getSnapshot);
|
|
1322
|
+
};
|
|
1049
1323
|
var useSchematicIsPending = (opts) => {
|
|
1050
1324
|
const client = useSchematicClient(opts);
|
|
1051
1325
|
const subscribe = (0, import_react2.useCallback)(
|