@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,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
|
|
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
|
|
34
|
-
iterable: "Symbol" in
|
|
35
|
-
blob: "FileReader" in
|
|
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
|
|
44
|
-
arrayBuffer: "ArrayBuffer" in
|
|
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
|
-
|
|
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
|
|
192
|
-
chars[
|
|
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
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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
|
|
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
|
-
|
|
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:
|
|
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 =
|
|
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
|
|
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 === "" &&
|
|
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
|
|
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 (!
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
561
|
-
|
|
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
|
-
|
|
740
|
+
flagCheckListeners = {};
|
|
593
741
|
flagValueListeners = {};
|
|
594
742
|
isPending = true;
|
|
595
743
|
isPendingListeners = /* @__PURE__ */ new Set();
|
|
596
744
|
storage;
|
|
597
745
|
useWebSocket = false;
|
|
598
|
-
|
|
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
|
}
|
|
@@ -625,37 +772,89 @@ var Schematic = class {
|
|
|
625
772
|
});
|
|
626
773
|
}
|
|
627
774
|
}
|
|
628
|
-
|
|
629
|
-
|
|
775
|
+
/**
|
|
776
|
+
* Get value for a single flag.
|
|
777
|
+
* In WebSocket mode, returns cached values if connection is active, otherwise establishes
|
|
778
|
+
* new connection and then returns the requestedvalue. Falls back to REST API if WebSocket
|
|
779
|
+
* connection fails.
|
|
780
|
+
* In REST mode, makes an API call for each check.
|
|
781
|
+
*/
|
|
630
782
|
async checkFlag(options) {
|
|
631
783
|
const { fallback = false, key } = options;
|
|
632
784
|
const context = options.context || this.context;
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
785
|
+
const contextStr = contextString(context);
|
|
786
|
+
if (!this.useWebSocket) {
|
|
787
|
+
const requestUrl = `${this.apiUrl}/flags/${key}/check`;
|
|
788
|
+
return fetch(requestUrl, {
|
|
789
|
+
method: "POST",
|
|
790
|
+
headers: {
|
|
791
|
+
...this.additionalHeaders ?? {},
|
|
792
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
793
|
+
"X-Schematic-Api-Key": this.apiKey
|
|
794
|
+
},
|
|
795
|
+
body: JSON.stringify(context)
|
|
796
|
+
}).then((response) => {
|
|
797
|
+
if (!response.ok) {
|
|
798
|
+
throw new Error("Network response was not ok");
|
|
799
|
+
}
|
|
800
|
+
return response.json();
|
|
801
|
+
}).then((response) => {
|
|
802
|
+
return CheckFlagResponseFromJSON(response).data.value;
|
|
803
|
+
}).catch((error) => {
|
|
804
|
+
console.error("There was a problem with the fetch operation:", error);
|
|
805
|
+
return fallback;
|
|
806
|
+
});
|
|
636
807
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
|
|
808
|
+
try {
|
|
809
|
+
const existingVals = this.checks[contextStr];
|
|
810
|
+
if (this.conn && typeof existingVals !== "undefined" && typeof existingVals[key] !== "undefined") {
|
|
811
|
+
return existingVals[key].value;
|
|
812
|
+
}
|
|
813
|
+
try {
|
|
814
|
+
await this.setContext(context);
|
|
815
|
+
} catch (error) {
|
|
816
|
+
console.error(
|
|
817
|
+
"WebSocket connection failed, falling back to REST:",
|
|
818
|
+
error
|
|
819
|
+
);
|
|
820
|
+
return this.fallbackToRest(key, context, fallback);
|
|
821
|
+
}
|
|
822
|
+
const contextVals = this.checks[contextStr] ?? {};
|
|
823
|
+
return contextVals[key]?.value ?? fallback;
|
|
824
|
+
} catch (error) {
|
|
825
|
+
console.error("Unexpected error in checkFlag:", error);
|
|
826
|
+
return fallback;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Helper method for falling back to REST API when WebSocket connection fails
|
|
831
|
+
*/
|
|
832
|
+
async fallbackToRest(key, context, fallback) {
|
|
833
|
+
try {
|
|
834
|
+
const requestUrl = `${this.apiUrl}/flags/${key}/check`;
|
|
835
|
+
const response = await fetch(requestUrl, {
|
|
836
|
+
method: "POST",
|
|
837
|
+
headers: {
|
|
838
|
+
...this.additionalHeaders ?? {},
|
|
839
|
+
"Content-Type": "application/json;charset=UTF-8",
|
|
840
|
+
"X-Schematic-Api-Key": this.apiKey
|
|
841
|
+
},
|
|
842
|
+
body: JSON.stringify(context)
|
|
843
|
+
});
|
|
647
844
|
if (!response.ok) {
|
|
648
845
|
throw new Error("Network response was not ok");
|
|
649
846
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
console.error("There was a problem with the fetch operation:", error);
|
|
847
|
+
const data = CheckFlagResponseFromJSON(await response.json());
|
|
848
|
+
return data?.data?.value ?? false;
|
|
849
|
+
} catch (error) {
|
|
850
|
+
console.error("REST API call failed, using fallback value:", error);
|
|
655
851
|
return fallback;
|
|
656
|
-
}
|
|
852
|
+
}
|
|
657
853
|
}
|
|
658
|
-
|
|
854
|
+
/**
|
|
855
|
+
* Make an API call to fetch all flag values for a given context.
|
|
856
|
+
* Recommended for use in REST mode only.
|
|
857
|
+
*/
|
|
659
858
|
checkFlags = async (context) => {
|
|
660
859
|
context = context || this.context;
|
|
661
860
|
const requestUrl = `${this.apiUrl}/flags/check`;
|
|
@@ -673,8 +872,9 @@ var Schematic = class {
|
|
|
673
872
|
throw new Error("Network response was not ok");
|
|
674
873
|
}
|
|
675
874
|
return response.json();
|
|
676
|
-
}).then((
|
|
677
|
-
|
|
875
|
+
}).then((responseJson) => {
|
|
876
|
+
const resp = CheckFlagsResponseFromJSON(responseJson);
|
|
877
|
+
return (resp?.data?.flags ?? []).reduce(
|
|
678
878
|
(accum, flag) => {
|
|
679
879
|
accum[flag.flag] = flag.value;
|
|
680
880
|
return accum;
|
|
@@ -683,21 +883,33 @@ var Schematic = class {
|
|
|
683
883
|
);
|
|
684
884
|
}).catch((error) => {
|
|
685
885
|
console.error("There was a problem with the fetch operation:", error);
|
|
686
|
-
return
|
|
886
|
+
return {};
|
|
687
887
|
});
|
|
688
888
|
};
|
|
689
|
-
|
|
889
|
+
/**
|
|
890
|
+
* Send an identify event.
|
|
891
|
+
* This will set the context for subsequent flag evaluation and events, and will also
|
|
892
|
+
* send an identify event to the Schematic API which will upsert a user and company.
|
|
893
|
+
*/
|
|
690
894
|
identify = (body) => {
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
895
|
+
try {
|
|
896
|
+
this.setContext({
|
|
897
|
+
company: body.company?.keys,
|
|
898
|
+
user: body.keys
|
|
899
|
+
});
|
|
900
|
+
} catch (error) {
|
|
901
|
+
console.error("Error setting context:", error);
|
|
902
|
+
}
|
|
695
903
|
return this.handleEvent("identify", body);
|
|
696
904
|
};
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
905
|
+
/**
|
|
906
|
+
* Set the flag evaluation context.
|
|
907
|
+
* In WebSocket mode, this will:
|
|
908
|
+
* 1. Open a websocket connection if not already open
|
|
909
|
+
* 2. Send the context to the server
|
|
910
|
+
* 3. Wait for initial flag values to be returned
|
|
911
|
+
* The promise resolves when initial flag values are received.
|
|
912
|
+
*/
|
|
701
913
|
setContext = async (context) => {
|
|
702
914
|
if (!this.useWebSocket) {
|
|
703
915
|
this.context = context;
|
|
@@ -711,10 +923,14 @@ var Schematic = class {
|
|
|
711
923
|
const socket = await this.conn;
|
|
712
924
|
await this.wsSendMessage(socket, context);
|
|
713
925
|
} catch (error) {
|
|
714
|
-
console.error("
|
|
926
|
+
console.error("Failed to establish WebSocket connection:", error);
|
|
927
|
+
throw error;
|
|
715
928
|
}
|
|
716
929
|
};
|
|
717
|
-
|
|
930
|
+
/**
|
|
931
|
+
* Send a track event
|
|
932
|
+
* Track usage for a company and/or user.
|
|
933
|
+
*/
|
|
718
934
|
track = (body) => {
|
|
719
935
|
const { company, user, event, traits } = body;
|
|
720
936
|
return this.handleEvent("track", {
|
|
@@ -786,6 +1002,9 @@ var Schematic = class {
|
|
|
786
1002
|
/**
|
|
787
1003
|
* Websocket management
|
|
788
1004
|
*/
|
|
1005
|
+
/**
|
|
1006
|
+
* If using websocket mode, close the connection when done.
|
|
1007
|
+
*/
|
|
789
1008
|
cleanup = async () => {
|
|
790
1009
|
if (this.conn) {
|
|
791
1010
|
try {
|
|
@@ -826,18 +1045,15 @@ var Schematic = class {
|
|
|
826
1045
|
let resolved = false;
|
|
827
1046
|
const messageHandler = (event) => {
|
|
828
1047
|
const message = JSON.parse(event.data);
|
|
829
|
-
if (!(contextString(context) in this.
|
|
830
|
-
this.
|
|
831
|
-
}
|
|
832
|
-
(message.flags ?? []).forEach(
|
|
833
|
-
(flag) => {
|
|
834
|
-
this.values[contextString(context)][flag.flag] = flag.value;
|
|
835
|
-
this.notifyFlagValueListeners(flag.flag, flag.value);
|
|
836
|
-
}
|
|
837
|
-
);
|
|
838
|
-
if (this.flagListener) {
|
|
839
|
-
this.flagListener(this.getFlagValues());
|
|
1048
|
+
if (!(contextString(context) in this.checks)) {
|
|
1049
|
+
this.checks[contextString(context)] = {};
|
|
840
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
|
+
});
|
|
841
1057
|
this.setIsPending(false);
|
|
842
1058
|
if (!resolved) {
|
|
843
1059
|
resolved = true;
|
|
@@ -877,18 +1093,21 @@ var Schematic = class {
|
|
|
877
1093
|
setIsPending = (isPending) => {
|
|
878
1094
|
this.isPending = isPending;
|
|
879
1095
|
this.isPendingListeners.forEach(
|
|
880
|
-
(listener) =>
|
|
1096
|
+
(listener) => notifyPendingListener(listener, isPending)
|
|
881
1097
|
);
|
|
882
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
|
+
};
|
|
883
1105
|
// flagValues state
|
|
884
1106
|
getFlagValue = (flagKey) => {
|
|
885
|
-
const
|
|
886
|
-
return
|
|
887
|
-
};
|
|
888
|
-
getFlagValues = () => {
|
|
889
|
-
const contextStr = contextString(this.context);
|
|
890
|
-
return this.values[contextStr] ?? {};
|
|
1107
|
+
const check = this.getFlagCheck(flagKey);
|
|
1108
|
+
return check?.value;
|
|
891
1109
|
};
|
|
1110
|
+
/** Register an event listener that will be notified with the boolean value for a given flag when this value changes */
|
|
892
1111
|
addFlagValueListener = (flagKey, listener) => {
|
|
893
1112
|
if (!(flagKey in this.flagValueListeners)) {
|
|
894
1113
|
this.flagValueListeners[flagKey] = /* @__PURE__ */ new Set();
|
|
@@ -898,12 +1117,40 @@ var Schematic = class {
|
|
|
898
1117
|
this.flagValueListeners[flagKey].delete(listener);
|
|
899
1118
|
};
|
|
900
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
|
+
};
|
|
901
1134
|
notifyFlagValueListeners = (flagKey, value) => {
|
|
902
1135
|
const listeners = this.flagValueListeners?.[flagKey] ?? [];
|
|
903
|
-
listeners.forEach((listener) =>
|
|
1136
|
+
listeners.forEach((listener) => notifyFlagValueListener(listener, value));
|
|
904
1137
|
};
|
|
905
1138
|
};
|
|
906
|
-
var
|
|
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) => {
|
|
907
1154
|
if (listener.length > 0) {
|
|
908
1155
|
listener(value);
|
|
909
1156
|
} else {
|
|
@@ -912,7 +1159,7 @@ var notifyListener = (listener, value) => {
|
|
|
912
1159
|
};
|
|
913
1160
|
|
|
914
1161
|
// src/context/schematic.tsx
|
|
915
|
-
import React, { createContext, useEffect, useMemo } from "react";
|
|
1162
|
+
import React, { createContext, useEffect, useMemo, useRef } from "react";
|
|
916
1163
|
import { jsx } from "react/jsx-runtime";
|
|
917
1164
|
var SchematicContext = createContext(
|
|
918
1165
|
null
|
|
@@ -923,16 +1170,19 @@ var SchematicProvider = ({
|
|
|
923
1170
|
publishableKey,
|
|
924
1171
|
...clientOpts
|
|
925
1172
|
}) => {
|
|
1173
|
+
const initialOptsRef = useRef({
|
|
1174
|
+
publishableKey,
|
|
1175
|
+
useWebSocket: clientOpts.useWebSocket ?? true,
|
|
1176
|
+
...clientOpts
|
|
1177
|
+
});
|
|
926
1178
|
const client = useMemo(() => {
|
|
927
|
-
const { useWebSocket = true } = clientOpts;
|
|
928
1179
|
if (providedClient) {
|
|
929
1180
|
return providedClient;
|
|
930
1181
|
}
|
|
931
|
-
return new Schematic(publishableKey, {
|
|
932
|
-
|
|
933
|
-
...clientOpts
|
|
1182
|
+
return new Schematic(initialOptsRef.current.publishableKey, {
|
|
1183
|
+
...initialOptsRef.current
|
|
934
1184
|
});
|
|
935
|
-
}, [providedClient
|
|
1185
|
+
}, [providedClient]);
|
|
936
1186
|
useEffect(() => {
|
|
937
1187
|
return () => {
|
|
938
1188
|
if (!providedClient) {
|
|
@@ -1004,6 +1254,27 @@ var useSchematicFlag = (key, opts) => {
|
|
|
1004
1254
|
}, [client, key, fallback]);
|
|
1005
1255
|
return useSyncExternalStore(subscribe, getSnapshot);
|
|
1006
1256
|
};
|
|
1257
|
+
var useSchematicFlagCheck = (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
|
+
};
|
|
1007
1278
|
var useSchematicIsPending = (opts) => {
|
|
1008
1279
|
const client = useSchematicClient(opts);
|
|
1009
1280
|
const subscribe = useCallback(
|
|
@@ -1014,12 +1285,15 @@ var useSchematicIsPending = (opts) => {
|
|
|
1014
1285
|
return useSyncExternalStore(subscribe, getSnapshot);
|
|
1015
1286
|
};
|
|
1016
1287
|
export {
|
|
1288
|
+
RuleType,
|
|
1017
1289
|
Schematic,
|
|
1018
1290
|
SchematicProvider,
|
|
1291
|
+
UsagePeriod,
|
|
1019
1292
|
useSchematic,
|
|
1020
1293
|
useSchematicContext,
|
|
1021
1294
|
useSchematicEvents,
|
|
1022
1295
|
useSchematicFlag,
|
|
1296
|
+
useSchematicFlagCheck,
|
|
1023
1297
|
useSchematicIsPending
|
|
1024
1298
|
};
|
|
1025
1299
|
/*! Bundled license information:
|